Initial commit

based on a stripped down xf86-video-msm.. the goal is to get something
with just EXA and remove the unneeded bits (like xv and dri2) for now.
They can be re-added later with removal of dependency on c2d2 if needed.
This commit is contained in:
Rob Clark
2012-03-31 12:30:18 -05:00
commit 085d5e28c8
17 changed files with 4557 additions and 0 deletions

25
.gitignore vendored Normal file
View File

@@ -0,0 +1,25 @@
.deps
.libs
Makefile
*.la
*.lo
*.o
*~
aclocal.m4
autom4te.cache
compile
config.h
config.h.in
config.log
config.status
depcomp
stamp-h1
Makefile.in
configure
libtool
ltmain.sh
config.guess
config.sub
install-sh
missing

22
Makefile.am Normal file
View File

@@ -0,0 +1,22 @@
# Copyright 2005 Adam Jackson.
#
# Permission is hereby granted, free of charge, to any person obtaining a
# copy of this software and associated documentation files (the "Software"),
# to deal in the Software without restriction, including without limitation
# on the rights to use, copy, modify, merge, publish, distribute, sub
# license, and/or sell copies of the Software, and to permit persons to whom
# the Software is furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice (including the next
# paragraph) shall be included in all copies or substantial portions of the
# Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
# ADAM JACKSON BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
# IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
AUTOMAKE_OPTIONS = foreign
SUBDIRS = src

12
autogen.sh Executable file
View File

@@ -0,0 +1,12 @@
#! /bin/sh
srcdir=`dirname $0`
test -z "$srcdir" && srcdir=.
ORIGDIR=`pwd`
cd $srcdir
autoreconf -v --install || exit 1
cd $ORIGDIR || exit $?
$srcdir/configure --enable-maintainer-mode "$@"

89
configure.ac Normal file
View File

@@ -0,0 +1,89 @@
# Copyright 2005 Adam Jackson.
#
# Permission is hereby granted, free of charge, to any person obtaining a
# copy of this software and associated documentation files (the "Software"),
# to deal in the Software without restriction, including without limitation
# on the rights to use, copy, modify, merge, publish, distribute, sub
# license, and/or sell copies of the Software, and to permit persons to whom
# the Software is furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice (including the next
# paragraph) shall be included in all copies or substantial portions of the
# Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
# ADAM JACKSON BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
# IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#
# Process this file with autoconf to produce a configure script
AC_PREREQ(2.57)
AC_INIT([xf86-video-freedreno],
0.0.1,
[],
xf86-video-freedreno)
AC_CONFIG_SRCDIR([Makefile.am])
AM_CONFIG_HEADER([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
AM_PROG_AS
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)
# Checks for pkg-config packages
PKG_CHECK_MODULES(XORG, [libdrm xorg-server xproto $REQUIRED_MODULES])
sdkdir=$(pkg-config --variable=sdkdir xorg-server)
PKG_CHECK_MODULES(XEXT, [xextproto >= 7.0.99.1],
HAVE_XEXTPROTO_71="yes"; AC_DEFINE(HAVE_XEXTPROTO_71, 1, [xextproto 7.1 available]),
HAVE_XEXTPROTO_71="no")
AM_CONDITIONAL(HAVE_XEXTPROTO_71, [ test "$HAVE_XEXTPROTO_71" = "yes" ])
# Checks for libraries.
# Checks for header files.
AC_HEADER_STDC
AC_SUBST([XORG_CFLAGS])
AC_SUBST([moduledir])
AC_SUBST([CFLAGS])
AC_SUBST([CCASFLAGS])
DRIVER_NAME=freedreno
AC_SUBST([DRIVER_NAME])
#XORG_MANPAGE_SECTIONS
XORG_RELEASE_VERSION
AC_OUTPUT([
Makefile
src/Makefile
])

20
src/Makefile.am Normal file
View File

@@ -0,0 +1,20 @@
freedreno_drv_la_LIBADD =
AM_CFLAGS = @XORG_CFLAGS@ -Wall -Werror -I$(top_srcdir)/system-includes/
freedreno_drv_la_LTLIBRARIES = freedreno_drv.la
freedreno_drv_la_LDFLAGS = -module -avoid-version
freedreno_drv_ladir = @moduledir@/drivers
freedreno_drv_la_SOURCES = \
msm-drm.c \
msm-driver.c \
msm-exa.c \
msm-output.c \
msm-display.c \
msm-cursor.c \
msm-pixmap.c
EXTRA_DIST = \
msm.h \
msm-drm.h

176
src/msm-cursor.c Normal file
View File

@@ -0,0 +1,176 @@
/* msm-cursor.c
*
* Copyright (c) 2009, Code Aurora Forum. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of Code Aurora nor
* the names of its contributors may be used to endorse or promote
* products derived from this software without specific prior written
* permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "xf86.h"
#include "xf86Crtc.h"
#include "xf86Cursor.h"
#include <sys/ioctl.h>
#include <errno.h>
#include "msm.h"
#define MSM_CURSOR_WIDTH 64
#define MSM_CURSOR_HEIGHT 64
#ifdef MSMFB_CURSOR
static void
_init_cursor(MSMPtr pMsm, struct fb_cursor *cursor)
{
memset(cursor, 0, sizeof(*cursor));
/* This is a workaround for a buggy kernel */
cursor->image.width = MSM_CURSOR_WIDTH;
cursor->image.height = MSM_CURSOR_HEIGHT;
cursor->image.depth = 32;
cursor->enable = pMsm->HWCursorState;
}
void
MSMSetCursorPosition(MSMPtr pMsm, int x, int y)
{
struct fb_cursor cursor;
_init_cursor(pMsm, &cursor);
if (x < 0)
x = 0;
if (y < 0)
y = 0;
cursor.set |= FB_CUR_SETPOS;
cursor.image.dx = x;
cursor.image.dy = y;
if (ioctl(pMsm->fd, MSMFB_CURSOR, &cursor))
ErrorF("%s: Error calling MSMBF_CURSOR\n", __FUNCTION__);
}
void
MSMCursorEnable(MSMPtr pMsm, Bool enable)
{
struct fb_cursor cursor;
_init_cursor(pMsm, &cursor);
pMsm->HWCursorState = cursor.enable = (enable == TRUE) ? 1 : 0;
if (ioctl(pMsm->fd, MSMFB_CURSOR, &cursor))
ErrorF("%s: Error calling MSMBF_CURSOR\n", __FUNCTION__);
}
void
MSMCursorLoadARGB(MSMPtr pMsm, CARD32 * image)
{
struct fb_cursor cursor;
_init_cursor(pMsm, &cursor);
cursor.set |= FB_CUR_SETIMAGE;
cursor.image.data = (char *)image;
/* BLEND_TRANSP_EN off */
cursor.image.bg_color = 0xFFFFFFFF;
/* Per pixel alpha on */
cursor.image.fg_color = 0;
if (ioctl(pMsm->fd, MSMFB_CURSOR, &cursor))
ErrorF("%s: Error calling MSMBF_CURSOR\n", __FUNCTION__);
}
Bool
MSMCursorInit(ScreenPtr pScreen)
{
ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
MSMPtr pMsm = MSMPTR(pScrn);
struct fb_cursor cursor;
_init_cursor(pMsm, &cursor);
/* Try to turn off the cursor - if this fails then we don't have
* HW cursor support */
cursor.enable = 0;
if (ioctl(pMsm->fd, MSMFB_CURSOR, &cursor)) {
xf86DrvMsg(pScreen->myNum, X_ERROR,
"Unable to enable the HW cursor: %s\n", strerror(errno));
return FALSE;
}
/* HWCursor is on the air, but not visible (yet) */
pMsm->HWCursorState = 0;
return xf86_cursors_init(pScreen, MSM_CURSOR_WIDTH, MSM_CURSOR_HEIGHT,
HARDWARE_CURSOR_TRUECOLOR_AT_8BPP |
HARDWARE_CURSOR_INVERT_MASK |
HARDWARE_CURSOR_AND_SOURCE_WITH_MASK |
HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_32 |
HARDWARE_CURSOR_ARGB);
}
#else
/* if MSMFB_CURSOR isn't defined, then this is an older version of the kernel
that doesn't support it - so just provide some dummy stuff here */
void
MSMCrtcSetCursorPosition(MSMPtr pMsm, int x, int y)
{
}
void
MSMCursorEnable(MSMPtr pMsm, Bool enable)
{
}
void
MSMCursorLoadARGB(MSMPtr pMsm, CARD32 * image)
{
}
Bool
MSMCursorInit(ScreenPtr pScreen)
{
return FALSE;
}
#endif

254
src/msm-display.c Normal file
View File

@@ -0,0 +1,254 @@
/* msm-output.c
k *
* Copyright (c) 2009, Code Aurora Forum. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of Code Aurora nor
* the names of its contributors may be used to endorse or promote
* products derived from this software without specific prior written
* permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#ifdef HAVE_XEXTPROTO_71
#include <X11/extensions/dpmsconst.h>
#else
#define DPMS_SERVER
#include <X11/extensions/dpms.h>
#endif
#include <sys/ioctl.h>
#include "xf86.h"
#include "xf86Crtc.h"
#include "xf86_OSlib.h"
#include "msm.h"
#include "msm-drm.h"
static void
MSMCrtcGammaSet(xf86CrtcPtr crtc,
CARD16 *red, CARD16 *green, CARD16 *blue, int size)
{
/* This is a new function that gets called by the DI code */
}
static void
MSMCrtcDPMS(xf86CrtcPtr crtc, int mode)
{
/* TODO: Implement DPMS */
}
static Bool
MSMCrtcLock(xf86CrtcPtr crtc)
{
return TRUE;
}
static void
MSMCrtcUnlock(xf86CrtcPtr crtc)
{
}
static void
MSMCrtcPrepare(xf86CrtcPtr crtc)
{
/* Blank the display before we change modes? */
}
static Bool
MSMCrtcModeFixup(xf86CrtcPtr crtc, DisplayModePtr mode,
DisplayModePtr adjmode)
{
ScrnInfoPtr pScrn = crtc->scrn;
MSMPtr pMsm = MSMPTR(pScrn);
if (mode->HDisplay > pMsm->mode_info.xres_virtual ||
mode->VDisplay > pMsm->mode_info.yres_virtual)
return FALSE;
return TRUE;
}
static void
MSMCrtcModeSet(xf86CrtcPtr crtc, DisplayModePtr mode,
DisplayModePtr adjmode, int x, int y)
{
int ret;
ScrnInfoPtr pScrn = crtc->scrn;
MSMPtr pMsm = MSMPTR(pScrn);
struct fb_var_screeninfo var;
int htotal, vtotal;
memcpy(&var, &pMsm->mode_info, sizeof(var));
htotal = var.xres + var.right_margin + var.hsync_len + var.left_margin;
var.xres = adjmode->HDisplay;
var.right_margin = adjmode->HSyncStart - adjmode->HDisplay;
var.hsync_len = adjmode->HSyncEnd - adjmode->HSyncStart;
var.left_margin = adjmode->HTotal - adjmode->HSyncEnd;
vtotal = var.yres + var.lower_margin + var.vsync_len + var.upper_margin;
var.yres = adjmode->VDisplay;
var.lower_margin = adjmode->VSyncStart - adjmode->VDisplay;
var.vsync_len = adjmode->VSyncEnd - adjmode->VSyncStart;
var.upper_margin = adjmode->VTotal - adjmode->VSyncEnd;
if (vtotal != adjmode->VTotal || htotal != adjmode->HTotal)
var.pixclock = pMsm->defaultVsync * adjmode->HTotal * adjmode->VTotal;
/*crtc->rotatedData!= NULL indicates that rotation has been requested
and shadow framebuffer has been allocated, so change the yoffset to make
the shadow framebuffer as visible screen. */
var.yoffset = (crtc->rotatedData && crtc->rotation != 1) ? var.yres : 0;
ret = ioctl(pMsm->fd, FBIOPUT_VSCREENINFO, &var);
if (ret)
xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Unable to change the mode: %m\n");
else {
/* Refresh the changed settings from the driver */
if (crtc->scrn->pScreen)
xf86_reload_cursors(crtc->scrn->pScreen);
ioctl(pMsm->fd, FBIOGET_VSCREENINFO, &pMsm->mode_info);
}
}
static void
MSMCrtcCommit(xf86CrtcPtr crtc)
{
}
static void *
MSMCrtcShadowAllocate(xf86CrtcPtr crtc, int width, int height)
{
ScrnInfoPtr pScrn = crtc->scrn;
MSMPtr pMsm = MSMPTR(pScrn);
/* (pMsm->fixed_info.line_length * pMsm->mode_info.yres) is the size of
original framebuufer. As buffer is already preallocated by kernel, so just
return the memory address after the end of original framebuffer as the
starting address of the shadow framebuffer.*/
memset((char*)(pMsm->fbmem + pMsm->mode_info.yres *
pMsm->fixed_info.line_length), 0, pMsm->mode_info.yres *
pMsm->fixed_info.line_length );
return (pMsm->fbmem + pMsm->mode_info.yres * pMsm->fixed_info.line_length);
}
static PixmapPtr
MSMCrtcShadowCreate(xf86CrtcPtr crtc, void *data, int width, int height)
{
ScrnInfoPtr pScrn = crtc->scrn;
PixmapPtr pNewPixmap = NULL;
MSMPtr pMsm = MSMPTR(pScrn);
if (!data)
data = MSMCrtcShadowAllocate(crtc, width, height);
/*The pitch, width and size of the rotated pixmap has to be the same as
those of the display framebuffer*/
pNewPixmap = GetScratchPixmapHeader(pScrn->pScreen,pMsm->mode_info.xres,
pMsm->mode_info.yres,pScrn->depth, pScrn->bitsPerPixel,
pMsm->fixed_info.line_length, data);
if (!pNewPixmap)
xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
"Unable to allocate shadow pixmap for rotation\n");
pMsm->rotatedPixmap = pNewPixmap;
return pNewPixmap;
}
static void
MSMCrtcShadowDestroy(xf86CrtcPtr crtc, PixmapPtr pPixmap, void *data)
{
ScrnInfoPtr pScrn = crtc->scrn;
MSMPtr pMsm = MSMPTR(pScrn);
pMsm->rotatedPixmap = NULL;
if (pPixmap)
FreeScratchPixmapHeader(pPixmap);
}
static void
MSMCrtcSetCursorPosition(xf86CrtcPtr crtc, int x, int y)
{
ScrnInfoPtr pScrn = crtc->scrn;
MSMPtr pMsm = MSMPTR(pScrn);
MSMSetCursorPosition(pMsm, x, y);
}
static void
MSMCrtcShowCursor(xf86CrtcPtr crtc)
{
ScrnInfoPtr pScrn = crtc->scrn;
MSMPtr pMsm = MSMPTR(pScrn);
MSMCursorEnable(pMsm, TRUE);
}
static void
MSMCrtcHideCursor(xf86CrtcPtr crtc)
{
ScrnInfoPtr pScrn = crtc->scrn;
MSMPtr pMsm = MSMPTR(pScrn);
MSMCursorEnable(pMsm, FALSE);
}
static void
MSMCrtcLoadCursorARGB(xf86CrtcPtr crtc, CARD32 * image)
{
ScrnInfoPtr pScrn = crtc->scrn;
MSMPtr pMsm = MSMPTR(pScrn);
MSMCursorLoadARGB(pMsm, image);
}
static const xf86CrtcFuncsRec MSMCrtcFuncs = {
.dpms = MSMCrtcDPMS,
.lock = MSMCrtcLock,
.unlock = MSMCrtcUnlock,
.mode_fixup = MSMCrtcModeFixup,
.prepare = MSMCrtcPrepare,
.mode_set = MSMCrtcModeSet,
.commit = MSMCrtcCommit,
.shadow_create = MSMCrtcShadowCreate,
.shadow_allocate = MSMCrtcShadowAllocate,
.shadow_destroy = MSMCrtcShadowDestroy,
.set_cursor_position = MSMCrtcSetCursorPosition,
.show_cursor = MSMCrtcShowCursor,
.hide_cursor = MSMCrtcHideCursor,
.load_cursor_argb = MSMCrtcLoadCursorARGB,
.gamma_set = MSMCrtcGammaSet,
.destroy = NULL, /* XXX */
};
void
MSMCrtcSetup(ScrnInfoPtr pScrn)
{
xf86CrtcPtr crtc = xf86CrtcCreate(pScrn, &MSMCrtcFuncs);
crtc->driver_private = NULL;
}

1062
src/msm-driver.c Normal file

File diff suppressed because it is too large Load Diff

532
src/msm-drm.c Normal file
View File

@@ -0,0 +1,532 @@
/* msm-drm.c
*
* Copyright (c) 2009, Code Aurora Forum. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of Code Aurora nor
* the names of its contributors may be used to endorse or promote
* products derived from this software without specific prior written
* permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <unistd.h>
#include <sys/ioctl.h>
#include <sys/mman.h>
#include <sys/errno.h>
#include <xf86drm.h>
#include <drm.h>
#include <drm/kgsl_drm.h>
#include "msm.h"
#include "msm-drm.h"
static int drm_version;
static int
msm_drm_get_version(int fd)
{
struct drm_version version;
memset(&version, 0, sizeof(version));
if (ioctl(fd, DRM_IOCTL_VERSION, &version)) {
ErrorF("%s: Unable to get the DRM version\n", __FUNCTION__);
return -1;
}
drm_version = (version.version_major << 16);
drm_version |= version.version_minor & 0xFFFF;
return 0;
}
int
msm_drm_bo_set_memtype(struct msm_drm_bo *bo, int type)
{
static int ebionly = 0;
int ret;
struct drm_kgsl_gem_memtype mtype;
if (bo == NULL || bo->handle == 0)
return -1;
/* Only fail the ioctl() once - the other times just quietly
* force the mode to EBI - see below */
if (ebionly) {
bo->memtype = DRM_KGSL_GEM_TYPE_EBI;
return 0;
}
switch(type) {
case MSM_DRM_MEMTYPE_KMEM:
bo->memtype = DRM_KGSL_GEM_TYPE_KMEM;
break;
case MSM_DRM_MEMTYPE_EBI:
bo->memtype = DRM_KGSL_GEM_TYPE_EBI;
break;
case MSM_DRM_MEMTYPE_SMI:
bo->memtype = DRM_KGSL_GEM_TYPE_SMI;
break;
case MSM_DRM_MEMTYPE_KMEM_NOCACHE:
bo->memtype = DRM_KGSL_GEM_TYPE_KMEM_NOCACHE;
break;
default:
return -1;
}
memset(&mtype, 0, sizeof(mtype));
mtype.handle = bo->handle;
mtype.type = bo->memtype;
ret = ioctl(bo->fd, DRM_IOCTL_KGSL_GEM_SETMEMTYPE, &mtype);
if (ret) {
/* If the ioctl() isn't supported, then the legacy behavior
* is to put everything is in EBI */
if (errno == EINVAL) {
ErrorF("DRM: DRM_IOCTL_KGSL_GEM_SETMEMTYPE is not supported.\n");
ErrorF(" All offscreen memory will be in EBI\n");
bo->memtype = DRM_KGSL_GEM_TYPE_EBI;
/* Set a flag so we don't come in here and fail for every
* allocation */
ebionly = 1;
return 0;
}
}
return ret;
}
int
msm_drm_bo_get_memtype(struct msm_drm_bo *bo)
{
struct drm_kgsl_gem_memtype mtype;
int ret;
if (bo == NULL || bo->handle == 0)
return -1;
if (bo->memtype < 0) {
memset(&mtype, 0, sizeof(mtype));
mtype.handle = bo->handle;
ret = ioctl(bo->fd, DRM_IOCTL_KGSL_GEM_SETMEMTYPE, &mtype);
if (ret)
return ret;
}
switch(bo->memtype) {
case DRM_KGSL_GEM_TYPE_KMEM:
return MSM_DRM_MEMTYPE_KMEM;
case DRM_KGSL_GEM_TYPE_KMEM_NOCACHE:
return MSM_DRM_MEMTYPE_KMEM_NOCACHE;
case DRM_KGSL_GEM_TYPE_EBI:
return MSM_DRM_MEMTYPE_EBI;
case DRM_KGSL_GEM_TYPE_SMI:
return MSM_DRM_MEMTYPE_SMI;
}
return -1;
}
void
_msm_drm_bo_free(struct msm_drm_bo *bo)
{
struct drm_gem_close close;
if (bo == NULL || bo->handle == 0)
return;
if (bo->hostptr)
munmap((void *) bo->hostptr, bo->size * bo->count);
memset(&close, 0, sizeof(close));
close.handle = bo->handle;
ioctl(bo->fd, DRM_IOCTL_GEM_CLOSE, &close);
free(bo);
}
struct msm_drm_bo *
msm_drm_bo_create(MSMPtr pMsm, int fd, int size, int type)
{
struct drm_kgsl_gem_create create;
struct msm_drm_bo *bo;
int ret;
size = (size + (getpagesize() - 1)) & ~(getpagesize() - 1);
if (size == 0)
return NULL;
/* We only cache the default pixmap type */
if (pMsm->cachedBo && type == pMsm->pixmapMemtype) {
if (pMsm->cachedBo->size == size) {
bo = pMsm->cachedBo;
pMsm->cachedBo = NULL;
return bo;
}
_msm_drm_bo_free(pMsm->cachedBo);
pMsm->cachedBo = NULL;
}
memset(&create, 0, sizeof(create));
create.size = size;
ret = ioctl(fd, DRM_IOCTL_KGSL_GEM_CREATE, &create);
if (ret)
return NULL;
bo = calloc(1, sizeof(*bo));
if (bo == NULL)
return NULL;
bo->size = size;
bo->handle = create.handle;
bo->fd = fd;
bo->active = 0;
bo->count = 1;
/* All memory defaults to EBI */
bo->memtype = DRM_KGSL_GEM_TYPE_EBI;
if (msm_drm_bo_set_memtype(bo, type)) {
ErrorF("Unable to set the memory type\n");
_msm_drm_bo_free(bo);
return NULL;
}
return bo;
}
int
msm_drm_bo_flink(struct msm_drm_bo *bo, unsigned int *name)
{
struct drm_gem_flink flink;
int ret;
memset(&flink, 0, sizeof(flink));
if (bo == NULL)
return -1;
flink.handle = bo->handle;
ret = ioctl(bo->fd, DRM_IOCTL_GEM_FLINK, &flink);
if (ret)
return -1;
bo->name = flink.name;
if (name)
*name = flink.name;
return 0;
}
int
msm_drm_bo_alloc(struct msm_drm_bo *bo)
{
struct drm_kgsl_gem_alloc alloc;
int ret;
if (bo == NULL)
return -1;
/* If the offset is set, then assume it has been allocated */
if (bo->offset != 0)
return 0;
memset(&alloc, 0, sizeof(alloc));
alloc.handle = bo->handle;
ret = ioctl(bo->fd, DRM_IOCTL_KGSL_GEM_ALLOC, &alloc);
if (ret) {
/* if the ioctl isn't supported, then use the legacy PREP ioctl */
if (errno == EINVAL) {
struct drm_kgsl_gem_prep prep;
ErrorF("DRM: DRM_IOCTL_KGSL_GEM_ALLOC is not supported.\n");
memset(&prep, 0, sizeof(prep));
prep.handle = bo->handle;
ret = ioctl(bo->fd, DRM_IOCTL_KGSL_GEM_PREP, &prep);
if (ret)
return -1;
bo->offset = prep.offset;
bo->gpuaddr[0] = prep.phys;
return 0;
}
return ret;
}
bo->offset = alloc.offset;
return 0;
}
int
msm_drm_bo_bind_gpu(struct msm_drm_bo *bo)
{
struct drm_kgsl_gem_bind_gpu bind;
int ret;
if (bo->gpuaddr[0])
return 0;
if (bo == NULL)
return -1;
bind.handle = bo->handle;
ret = ioctl(bo->fd, DRM_IOCTL_KGSL_GEM_BIND_GPU, &bind);
if (ret)
return ret;
bo->gpuaddr[0] = bind.gpuptr;
/* If the ioctls are in place, then get the buffer info to get the GPU
addresses directly */
#ifdef DRM_IOCTL_KGSL_GEM_GET_BUFINFO
{
int i;
struct drm_kgsl_gem_bufinfo bufinfo;
bufinfo.handle = bo->handle;
ret = ioctl(bo->fd, DRM_IOCTL_KGSL_GEM_GET_BUFINFO, &bufinfo);
for(i = 0; !ret && i < bufinfo.count; i++)
bo->gpuaddr[i] = bufinfo.gpuaddr[i];
}
#endif
return 0;
}
int
msm_drm_bo_map(struct msm_drm_bo *bo)
{
int ret, i;
unsigned int mapsize;
if (bo == NULL)
return -1;
/* Already mapped */
if (bo->hostptr != NULL)
return 0;
if (!bo->offset) {
ret = msm_drm_bo_alloc(bo);
if (ret) {
ErrorF("DRM: Unable to allocate: %m\n");
return ret;
}
}
mapsize = bo->size;
bo->offsets[0] = 0;
#ifdef DRM_IOCTL_KGSL_GEM_GET_BUFINFO
{
struct drm_kgsl_gem_bufinfo bufinfo;
bufinfo.handle = bo->handle;
ret = ioctl(bo->fd, DRM_IOCTL_KGSL_GEM_GET_BUFINFO, &bufinfo);
if (ret == 0) {
for(i = 0; i < bufinfo.count; i++) {
bo->offsets[i] = bufinfo.offset[i];
bo->gpuaddr[i] = bufinfo.gpuaddr[i];
}
bo->count = bufinfo.count;
bo->active = bufinfo.active;
mapsize = bo->size * bo->count;
}
}
#endif
bo->hostptr = mmap(0, mapsize, PROT_READ | PROT_WRITE, MAP_SHARED,
bo->fd, bo->offset);
if (bo->hostptr == MAP_FAILED) {
ErrorF("DRM: Unable to map: %m\n");
return -1;
}
for(i = 0; i < bo->count; i++)
bo->virtaddr[i] = (void *) bo->hostptr + bo->offsets[i];
return 0;
}
void
msm_drm_bo_unmap(struct msm_drm_bo *bo)
{
if (bo == NULL)
return;
/* For the moment, always leave buffers mapped */
#if 0
if (bo->hostptr)
munmap((void *) bo->hostptr, bo->size);
bo->hostptr = 0;
#endif
}
void
msm_drm_bo_free(MSMPtr pMsm, struct msm_drm_bo *bo)
{
if (bo == NULL || bo->handle == 0)
return;
if (bo->memtype == pMsm->pixmapMemtype &&
bo->count == 1 &&
bo->name == 0) {
if (pMsm->cachedBo)
_msm_drm_bo_free(pMsm->cachedBo);
pMsm->cachedBo = bo;
}
else
_msm_drm_bo_free(bo);
}
/* Set the next buffer in the list as active */
#ifdef DRM_IOCTL_KGSL_GEM_SET_ACTIVE
int msm_drm_bo_swap_buffers(struct msm_drm_bo *bo)
{
struct drm_kgsl_gem_active active;
int ret = 0;
if (drm_version < 0x00020001)
return -1;
active.active = bo->active + 1;
if (active.active == bo->count)
active.active = 0;
active.handle = bo->handle;
ret= ioctl(bo->fd, DRM_IOCTL_KGSL_GEM_SET_ACTIVE, &active);
if (!ret)
bo->active = active.active;
return ret;
}
#else
int msm_drm_bo_swap_buffers(struct msm_drm_bo *bo)
{
return -1;
}
#endif
#ifdef DRM_IOCTL_KGSL_GEM_SET_BUFCOUNT
int msm_drm_bo_set_bufcount(struct msm_drm_bo *bo, int count)
{
struct drm_kgsl_gem_bufcount bcount;
int ret;
if (drm_version < 0x00020001)
return -1;
bcount.bufcount = count;
bcount.handle = bo->handle;
ret = ioctl(bo->fd, DRM_IOCTL_KGSL_GEM_SET_BUFCOUNT, &bcount);
if (!ret)
bo->count = count;
return ret;
}
#endif
int msm_drm_bo_support_swap(int fd)
{
if (!drm_version)
msm_drm_get_version(fd);
return (drm_version >= 0x00020001) ? 1 : 0;
}
/* Create a buffer object for the framebuffer */
struct msm_drm_bo *
msm_drm_bo_create_fb(MSMPtr pMsm, int drmfd, int fbfd, int size)
{
struct drm_kgsl_gem_create_fd createfd;
struct msm_drm_bo *bo;
int ret;
memset(&createfd, 0, sizeof(createfd));
createfd.fd = fbfd;
ret = ioctl(drmfd, DRM_IOCTL_KGSL_GEM_CREATE_FD, &createfd);
if (ret)
return NULL;
bo = calloc(1, sizeof(*bo));
if (bo == NULL)
return NULL;
bo->size = size;
bo->handle = createfd.handle;
bo->fd =drmfd;
bo->active = 0;
bo->count = 1;
bo->memtype = DRM_KGSL_GEM_TYPE_FD_FBMEM;
return bo;
}

75
src/msm-drm.h Normal file
View File

@@ -0,0 +1,75 @@
/* msm-drm.h
*
* Copyright (c) 2009, Code Aurora Forum. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of Code Aurora nor
* the names of its contributors may be used to endorse or promote
* products derived from this software without specific prior written
* permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef MSM_DRM_H_
#define MSM_DRM_H_
#include <drm.h>
#include <drm/kgsl_drm.h>
#define MSM_DRM_MEMTYPE_EBI 0
#define MSM_DRM_MEMTYPE_SMI 1
#define MSM_DRM_MEMTYPE_KMEM 2
#define MSM_DRM_MEMTYPE_KMEM_NOCACHE 3
struct msm_drm_bo {
int fd;
unsigned int name;
int memtype;
unsigned int size;
unsigned int handle;
int count;
void *hostptr;
void *virtaddr[3];
unsigned int offsets[3];
unsigned int gpuaddr[3];
int ref;
int active;
unsigned long long offset;
};
int msm_drm_init(int fd);
struct msm_drm_bo *msm_drm_bo_create(MSMPtr pMsm, int fd, int size, int type);
int msm_drm_bo_flink(struct msm_drm_bo *bo, unsigned int *name);
void msm_drm_bo_free(MSMPtr pMsm, struct msm_drm_bo *bo);
void msm_drm_bo_unmap(struct msm_drm_bo *bo);
int msm_drm_bo_map(struct msm_drm_bo *bo);
int msm_drm_bo_bind_gpu(struct msm_drm_bo *bo);
int msm_drm_bo_alloc(struct msm_drm_bo *bo);
int msm_drm_bo_set_memtype(struct msm_drm_bo *bo, int type);
int msm_drm_bo_get_memtype(struct msm_drm_bo *bo);
int msm_drm_bo_set_bufcount(struct msm_drm_bo *bo, int count);
int msm_drm_bo_swap_buffers(struct msm_drm_bo *bo);
int msm_drm_bo_support_swap(int fd);
struct msm_drm_bo *msm_drm_bo_create_fb(MSMPtr pMsm, int drmfd, int fbfd,
int size);
#endif

689
src/msm-exa.c Normal file
View File

@@ -0,0 +1,689 @@
/* msm-exa.c
*
* Copyright (c) 2009-2010, Code Aurora Forum. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of Code Aurora nor
* the names of its contributors may be used to endorse or promote
* products derived from this software without specific prior written
* permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "xf86.h"
#include "exa.h"
#include "msm.h"
#include "msm-drm.h"
#define xFixedtoDouble(_f) (double) ((_f)/(double) xFixed1)
#define ENABLE_EXA_TRACE 1
#define ENABLE_SW_FALLBACK_REPORTS 1
#define SCREEN(pDraw) \
ScrnInfoPtr pScrn = xf86Screens[((DrawablePtr)(pDraw))->pScreen->myNum];
#define TRACE_EXA(fmt, ...) do { \
if (ENABLE_EXA_TRACE) \
DEBUG_MSG(fmt, ##__VA_ARGS__); \
} while (0)
#define EXA_FAIL_IF(cond) do { \
if (cond) { \
if (ENABLE_SW_FALLBACK_REPORTS) { \
DEBUG_MSG("fallback: " #cond); \
} \
return FALSE; \
} \
} while (0)
#if 0
/* Get the length of the vector represented by (x,y) */
static inline double
vector_length(double x, double y)
{
return sqrt((x*x) + (y*y));
}
static inline void
vector_normalize(double *x, double *y)
{
double len = vector_length(*x, *y);
if (len != 0.0) {
*x /= len;
*y /= len;
}
}
static void
transform_get_translate(PictTransform *t, double *x, double *y)
{
double scale = xFixedtoDouble(t->matrix[2][2]);
if (scale == 0)
return;
*x = xFixedtoDouble(t->matrix[0][2]) / scale;
*y = xFixedtoDouble(t->matrix[1][2]) / scale;
}
static void
transform_get_scale(PictTransform *t, double *xscale, double *yscale)
{
double scale = xFixedtoDouble(t->matrix[2][2]);
double xs, ys;
if (scale == 0)
return;
xs = (vector_length(xFixedtoDouble(t->matrix[0][0]) / scale,
xFixedtoDouble(t->matrix[0][1]) / scale));
ys = (vector_length(xFixedtoDouble(t->matrix[1][0]) / scale,
xFixedtoDouble(t->matrix[1][1]) / scale));
/* The returned value is the inverse of what we calculate, because
the matrix is mapping the transformed surface back to the source
surface */
if (xs)
xs = 1/xs;
if (ys)
ys = 1/ys;
*xscale = xs;
*yscale = ys;
}
static void
transform_get_rotate(PictTransform *t, double *d)
{
double row[2][2];
double ret;
double scale = xFixedtoDouble(t->matrix[2][2]);
if (scale == 0)
return;
row[0][0] = xFixedtoDouble(t->matrix[0][0]) / scale;
row[0][1] = xFixedtoDouble(t->matrix[0][1]) / scale;
row[1][0] = xFixedtoDouble(t->matrix[1][0]) / scale;
row[1][1] = xFixedtoDouble(t->matrix[1][1]) / scale;
vector_normalize(&row[0][0], &row[0][1]);
vector_normalize(&row[1][0], &row[1][1]);
ret = atan2(row[0][1], row[0][0]) - atan2(0, 1);
*d = ret >= 0 ? ret : (2 * M_PI) + ret;
}
#endif
/**
* PrepareSolid() sets up the driver for doing a solid fill.
* @param pPixmap Destination pixmap
* @param alu raster operation
* @param planemask write mask for the fill
* @param fg "foreground" color for the fill
*
* This call should set up the driver for doing a series of solid fills
* through the Solid() call. The alu raster op is one of the GX*
* graphics functions listed in X.h, and typically maps to a similar
* single-byte "ROP" setting in all hardware. The planemask controls
* which bits of the destination should be affected, and will only represent
* the bits up to the depth of pPixmap. The fg is the pixel value of the
* foreground color referred to in ROP descriptions.
*
* Note that many drivers will need to store some of the data in the driver
* private record, for sending to the hardware with each drawing command.
*
* The PrepareSolid() call is required of all drivers, but it may fail for any
* reason. Failure results in a fallback to software rendering.
*/
static Bool
MSMPrepareSolid(PixmapPtr pPixmap, int alu, Pixel planemask, Pixel fg)
{
SCREEN(pPixmap);
TRACE_EXA("%p <- alu=%x, planemask=%08x, fg=%08x",
pPixmap, alu, (unsigned int)planemask, (unsigned int)fg);
EXA_FAIL_IF(planemask != FB_ALLONES);
EXA_FAIL_IF(alu != GXcopy);
EXA_FAIL_IF(TRUE);
return TRUE;
}
/**
* Solid() performs a solid fill set up in the last PrepareSolid() call.
*
* @param pPixmap destination pixmap
* @param x1 left coordinate
* @param y1 top coordinate
* @param x2 right coordinate
* @param y2 bottom coordinate
*
* Performs the fill set up by the last PrepareSolid() call, covering the
* area from (x1,y1) to (x2,y2) in pPixmap. Note that the coordinates are
* in the coordinate space of the destination pixmap, so the driver will
* need to set up the hardware's offset and pitch for the destination
* coordinates according to the pixmap's offset and pitch within
* framebuffer. This likely means using exaGetPixmapOffset() and
* exaGetPixmapPitch().
*
* This call is required if PrepareSolid() ever succeeds.
*/
static void
MSMSolid(PixmapPtr pPixmap, int x1, int y1, int x2, int y2)
{
SCREEN(pPixmap);
TRACE_EXA("x1=%d\ty1=%d\tx2=%d\ty2=%d", x1, y1, x2, y2);
}
/**
* DoneSolid() finishes a set of solid fills.
*
* @param pPixmap destination pixmap.
*
* The DoneSolid() call is called at the end of a series of consecutive
* Solid() calls following a successful PrepareSolid(). This allows drivers
* to finish up emitting drawing commands that were buffered, or clean up
* state from PrepareSolid().
*
* This call is required if PrepareSolid() ever succeeds.
*/
static void
MSMDoneSolid(PixmapPtr pPixmap)
{
}
/**
* PrepareCopy() sets up the driver for doing a copy within video
* memory.
*
* @param pSrcPixmap source pixmap
* @param pDstPixmap destination pixmap
* @param dx X copy direction
* @param dy Y copy direction
* @param alu raster operation
* @param planemask write mask for the fill
*
* This call should set up the driver for doing a series of copies from the
* the pSrcPixmap to the pDstPixmap. The dx flag will be positive if the
* hardware should do the copy from the left to the right, and dy will be
* positive if the copy should be done from the top to the bottom. This
* is to deal with self-overlapping copies when pSrcPixmap == pDstPixmap.
* If your hardware can only support blits that are (left to right, top to
* bottom) or (right to left, bottom to top), then you should set
* #EXA_TWO_BITBLT_DIRECTIONS, and EXA will break down Copy operations to
* ones that meet those requirements. The alu raster op is one of the GX*
* graphics functions listed in X.h, and typically maps to a similar
* single-byte "ROP" setting in all hardware. The planemask controls which
* bits of the destination should be affected, and will only represent the
* bits up to the depth of pPixmap.
*
* Note that many drivers will need to store some of the data in the driver
* private record, for sending to the hardware with each drawing command.
*
* The PrepareCopy() call is required of all drivers, but it may fail for any
* reason. Failure results in a fallback to software rendering.
*/
static Bool
MSMPrepareCopy(PixmapPtr pSrcPixmap, PixmapPtr pDstPixmap, int dx, int dy,
int alu, Pixel planemask)
{
SCREEN(pDstPixmap);
TRACE_EXA("%p <- %p", pDstPixmap, pSrcPixmap);
EXA_FAIL_IF(planemask != FB_ALLONES);
EXA_FAIL_IF(alu != GXcopy);
EXA_FAIL_IF(TRUE);
return TRUE;
}
/**
* Copy() performs a copy set up in the last PrepareCopy call.
*
* @param pDstPixmap destination pixmap
* @param srcX source X coordinate
* @param srcY source Y coordinate
* @param dstX destination X coordinate
* @param dstY destination Y coordinate
* @param width width of the rectangle to be copied
* @param height height of the rectangle to be copied.
*
* Performs the copy set up by the last PrepareCopy() call, copying the
* rectangle from (srcX, srcY) to (srcX + width, srcY + width) in the source
* pixmap to the same-sized rectangle at (dstX, dstY) in the destination
* pixmap. Those rectangles may overlap in memory, if
* pSrcPixmap == pDstPixmap. Note that this call does not receive the
* pSrcPixmap as an argument -- if it's needed in this function, it should
* be stored in the driver private during PrepareCopy(). As with Solid(),
* the coordinates are in the coordinate space of each pixmap, so the driver
* will need to set up source and destination pitches and offsets from those
* pixmaps, probably using exaGetPixmapOffset() and exaGetPixmapPitch().
*
* This call is required if PrepareCopy ever succeeds.
*/
static void
MSMCopy(PixmapPtr pDstPixmap, int srcX, int srcY, int dstX, int dstY,
int width, int height)
{
SCREEN(pDstPixmap);
TRACE_EXA("srcX=%d\tsrcY=%d\tdstX=%d\tdstY=%d\twidth=%d\theight=%d",
srcX, srcY, dstX, dstY, width, height);
}
/**
* DoneCopy() finishes a set of copies.
*
* @param pPixmap destination pixmap.
*
* The DoneCopy() call is called at the end of a series of consecutive
* Copy() calls following a successful PrepareCopy(). This allows drivers
* to finish up emitting drawing commands that were buffered, or clean up
* state from PrepareCopy().
*
* This call is required if PrepareCopy() ever succeeds.
*/
static void
MSMDoneCopy(PixmapPtr pDstPixmap)
{
}
/**
* CheckComposite() checks to see if a composite operation could be
* accelerated.
*
* @param op Render operation
* @param pSrcPicture source Picture
* @param pMaskPicture mask picture
* @param pDstPicture destination Picture
*
* The CheckComposite() call checks if the driver could handle acceleration
* of op with the given source, mask, and destination pictures. This allows
* drivers to check source and destination formats, supported operations,
* transformations, and component alpha state, and send operations it can't
* support to software rendering early on. This avoids costly pixmap
* migration to the wrong places when the driver can't accelerate
* operations. Note that because migration hasn't happened, the driver
* can't know during CheckComposite() what the offsets and pitches of the
* pixmaps are going to be.
*
* See PrepareComposite() for more details on likely issues that drivers
* will have in accelerating Composite operations.
*
* The CheckComposite() call is recommended if PrepareComposite() is
* implemented, but is not required.
*/
static Bool
MSMCheckComposite(int op, PicturePtr pSrcPicture, PicturePtr pMaskPicture,
PicturePtr pDstPicture)
{
SCREEN(pDstPicture->pDrawable);
TRACE_EXA("%p <- %p (%p)", pDstPicture, pSrcPicture, pMaskPicture);
EXA_FAIL_IF(TRUE);
return TRUE;
}
/**
* PrepareComposite() sets up the driver for doing a Composite operation
* described in the Render extension protocol spec.
*
* @param op Render operation
* @param pSrcPicture source Picture
* @param pMaskPicture mask picture
* @param pDstPicture destination Picture
* @param pSrc source pixmap
* @param pMask mask pixmap
* @param pDst destination pixmap
*
* This call should set up the driver for doing a series of Composite
* operations, as described in the Render protocol spec, with the given
* pSrcPicture, pMaskPicture, and pDstPicture. The pSrc, pMask, and
* pDst are the pixmaps containing the pixel data, and should be used for
* setting the offset and pitch used for the coordinate spaces for each of
* the Pictures.
*
* Notes on interpreting Picture structures:
* - The Picture structures will always have a valid pDrawable.
* - The Picture structures will never have alphaMap set.
* - The mask Picture (and therefore pMask) may be NULL, in which case the
* operation is simply src OP dst instead of src IN mask OP dst, and
* mask coordinates should be ignored.
* - pMarkPicture may have componentAlpha set, which greatly changes
* the behavior of the Composite operation. componentAlpha has no effect
* when set on pSrcPicture or pDstPicture.
* - The source and mask Pictures may have a transformation set
* (Picture->transform != NULL), which means that the source coordinates
* should be transformed by that transformation, resulting in scaling,
* rotation, etc. The PictureTransformPoint() call can transform
* coordinates for you. Transforms have no effect on Pictures when used
* as a destination.
* - The source and mask pictures may have a filter set. PictFilterNearest
* and PictFilterBilinear are defined in the Render protocol, but others
* may be encountered, and must be handled correctly (usually by
* PrepareComposite failing, and falling back to software). Filters have
* no effect on Pictures when used as a destination.
* - The source and mask Pictures may have repeating set, which must be
* respected. Many chipsets will be unable to support repeating on
* pixmaps that have a width or height that is not a power of two.
*
* If your hardware can't support source pictures (textures) with
* non-power-of-two pitches, you should set #EXA_OFFSCREEN_ALIGN_POT.
*
* Note that many drivers will need to store some of the data in the driver
* private record, for sending to the hardware with each drawing command.
*
* The PrepareComposite() call is not required. However, it is highly
* recommended for performance of antialiased font rendering and performance
* of cairo applications. Failure results in a fallback to software
* rendering.
*/
static Bool
MSMPrepareComposite(int op, PicturePtr pSrcPicture, PicturePtr pMaskPicture,
PicturePtr pDstPicture, PixmapPtr pSrc, PixmapPtr pMask, PixmapPtr pDst)
{
SCREEN(pDst);
TRACE_EXA("%p <- %p (%p)", pDst, pSrc, pMask);
EXA_FAIL_IF(TRUE);
return TRUE;
}
/**
* Composite() performs a Composite operation set up in the last
* PrepareComposite() call.
*
* @param pDstPixmap destination pixmap
* @param srcX source X coordinate
* @param srcY source Y coordinate
* @param maskX source X coordinate
* @param maskY source Y coordinate
* @param dstX destination X coordinate
* @param dstY destination Y coordinate
* @param width destination rectangle width
* @param height destination rectangle height
*
* Performs the Composite operation set up by the last PrepareComposite()
* call, to the rectangle from (dstX, dstY) to (dstX + width, dstY + height)
* in the destination Pixmap. Note that if a transformation was set on
* the source or mask Pictures, the source rectangles may not be the same
* size as the destination rectangles and filtering. Getting the coordinate
* transformation right at the subpixel level can be tricky, and rendercheck
* can test this for you.
*
* This call is required if PrepareComposite() ever succeeds.
*/
static void
MSMComposite(PixmapPtr pDst, int srcX, int srcY, int maskX, int maskY,
int dstX, int dstY, int width, int height)
{
SCREEN(pDst);
TRACE_EXA("srcX=%d\tsrcY=%d\tmaskX=%d\tmaskY=%d\tdstX=%d\tdstY=%d\twidth=%d\theight=%d",
srcX, srcY, maskX, maskY, dstX, dstY, width, height);
}
/**
* DoneComposite() finishes a set of Composite operations.
*
* @param pPixmap destination pixmap.
*
* The DoneComposite() call is called at the end of a series of consecutive
* Composite() calls following a successful PrepareComposite(). This allows
* drivers to finish up emitting drawing commands that were buffered, or
* clean up state from PrepareComposite().
*
* This call is required if PrepareComposite() ever succeeds.
*/
static void
MSMDoneComposite(PixmapPtr pDst)
{
}
/**
* MarkSync() requests that the driver mark a synchronization point,
* returning an driver-defined integer marker which could be requested for
* synchronization to later in WaitMarker(). This might be used in the
* future to avoid waiting for full hardware stalls before accessing pixmap
* data with the CPU, but is not important in the current incarnation of
* EXA.
*
* Note that drivers should call exaMarkSync() when they have done some
* acceleration, rather than their own MarkSync() handler, as otherwise EXA
* will be unaware of the driver's acceleration and not sync to it during
* fallbacks.
*
* MarkSync() is optional.
*/
static int
MSMMarkSync(ScreenPtr pScreen)
{
return 0;
}
/**
* WaitMarker() waits for all rendering before the given marker to have
* completed. If the driver does not implement MarkSync(), marker is
* meaningless, and all rendering by the hardware should be completed before
* WaitMarker() returns.
*
* Note that drivers should call exaWaitSync() to wait for all acceleration
* to finish, as otherwise EXA will be unaware of the driver having
* synchronized, resulting in excessive WaitMarker() calls.
*
* WaitMarker() is required of all drivers.
*/
static void
MSMWaitMarker(ScreenPtr pScreen, int marker)
{
}
static Bool
MSMPixmapIsOffscreen(PixmapPtr pPixmap)
{
ScreenPtr pScreen = pPixmap->drawable.pScreen;
MSMPtr pMsm = MSMPTR_FROM_PIXMAP(pPixmap);
struct msm_pixmap_priv *priv;
if ((pScreen->GetScreenPixmap(pScreen) == pPixmap) ||
(pMsm->rotatedPixmap == pPixmap)){
return TRUE;
}
priv = exaGetPixmapDriverPrivate(pPixmap);
if (priv && priv->bo)
return TRUE;
return FALSE;
}
static Bool
MSMPrepareAccess(PixmapPtr pPixmap, int index)
{
struct msm_pixmap_priv *priv;
priv = exaGetPixmapDriverPrivate(pPixmap);
if (!priv)
return FALSE;
if (!priv->bo)
return TRUE;
if (msm_drm_bo_map(priv->bo))
return FALSE;
if (pPixmap->devPrivate.ptr == NULL)
pPixmap->devPrivate.ptr = (void *) priv->bo->hostptr;
if (pPixmap->drawable.bitsPerPixel == 16 ||
pPixmap->drawable.bitsPerPixel == 32) {
priv->SavedPitch = pPixmap->devKind;
pPixmap->devKind = ((pPixmap->drawable.width + 31) & ~31) *
(pPixmap->drawable.bitsPerPixel >> 3);
}
return TRUE;
}
static void
MSMFinishAccess(PixmapPtr pPixmap, int index)
{
struct msm_pixmap_priv *priv;
priv = exaGetPixmapDriverPrivate(pPixmap);
if (!priv || !priv->bo)
return;
if (priv->SavedPitch) {
pPixmap->devKind = priv->SavedPitch;
priv->SavedPitch = 0;
}
pPixmap->devPrivate.ptr = NULL;
}
static void *
MSMCreatePixmap(ScreenPtr pScreen, int size, int align)
{
struct msm_pixmap_priv *priv;
ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
MSMPtr pMsm = MSMPTR(pScrn);
priv = calloc(1, sizeof(struct msm_pixmap_priv));
if (priv == NULL)
return NULL;
if (!size)
return priv;
priv->bo = msm_drm_bo_create(pMsm, pMsm->drmFD, size,
pMsm->pixmapMemtype);
if (priv->bo)
return priv;
free(priv);
return NULL;
}
static void
MSMDestroyPixmap(ScreenPtr pScreen, void *dpriv)
{
struct msm_pixmap_priv *priv = dpriv;
ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
MSMPtr pMsm = MSMPTR(pScrn);
if (!dpriv)
return;
if (priv->bo)
msm_drm_bo_free(pMsm, priv->bo);
free(dpriv);
}
Bool
MSMSetupExa(ScreenPtr pScreen)
{
ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
MSMPtr pMsm = MSMPTR(pScrn);
ExaDriverPtr pExa;
if (pMsm->pExa == NULL)
pMsm->pExa = exaDriverAlloc();
if (pMsm->pExa == NULL)
return FALSE;
pExa = pMsm->pExa;
/* This is the current major/minor that we support */
pExa->exa_major = 2;
pExa->exa_minor = 2;
pExa->memoryBase = pMsm->fbmem;
/* Max blit extents that hw supports */
pExa->maxX = 2048;
pExa->maxY = 2048;
pExa->flags = EXA_OFFSCREEN_PIXMAPS | EXA_HANDLES_PIXMAPS | EXA_SUPPORTS_PREPARE_AUX;
pExa->offScreenBase =
(pMsm->fixed_info.line_length * pMsm->mode_info.yres);
pExa->memorySize = pMsm->fixed_info.smem_len;
/* Align pixmap offsets along page boundaries */
pExa->pixmapOffsetAlign = 4096;
/* Align pixmap pitches to the maximum needed aligment for the
GPU - this ensures that we have enough room, and we adjust the
pitches down to the depth later */
pExa->pixmapPitchAlign = 128;
/* The maximum acceleratable pitch is 2048 pixels */
pExa->maxPitchPixels = 2048;
pExa->PrepareSolid = MSMPrepareSolid;
pExa->Solid = MSMSolid;
pExa->DoneSolid = MSMDoneSolid;
pExa->PrepareCopy = MSMPrepareCopy;
pExa->Copy = MSMCopy;
pExa->DoneCopy = MSMDoneCopy;
pExa->CheckComposite = MSMCheckComposite;
pExa->PrepareComposite = MSMPrepareComposite;
pExa->Composite = MSMComposite;
pExa->DoneComposite = MSMDoneComposite;
pExa->MarkSync = MSMMarkSync;
pExa->WaitMarker = MSMWaitMarker;
pExa->PixmapIsOffscreen = MSMPixmapIsOffscreen;
pExa->CreatePixmap = MSMCreatePixmap;
pExa->DestroyPixmap = MSMDestroyPixmap;
pExa->PrepareAccess = MSMPrepareAccess;
pExa->FinishAccess = MSMFinishAccess;
return exaDriverInit(pScreen, pMsm->pExa);
}

165
src/msm-output.c Normal file
View File

@@ -0,0 +1,165 @@
/* msm-output.c
*
* Copyright (c) 2009, Code Aurora Forum. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of Code Aurora nor
* the names of its contributors may be used to endorse or promote
* products derived from this software without specific prior written
* permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "xf86.h"
#include "xf86i2c.h"
#include "xf86Crtc.h"
#include "xf86_OSlib.h"
#include "X11/Xatom.h"
#include "randrstr.h"
#ifdef HAVE_XEXTPROTO_71
#include <X11/extensions/dpmsconst.h>
#else
#define DPMS_SERVER
#include <X11/extensions/dpms.h>
#endif
#include "msm.h"
static void
MSMOutputCreateResources(xf86OutputPtr output)
{
/* No custom properties are supported */
}
static Bool
MSMOutputSetProperty(xf86OutputPtr output, Atom property,
RRPropertyValuePtr value)
{
/* No custom properties are supported */
return TRUE;
}
static void
MSMOutputDPMS(xf86OutputPtr output, int mode)
{
/* DPMS is handled at the CRTC */
}
static void
MSMOutputPrepare(xf86OutputPtr output)
{
}
static void
MSMOutputCommit(xf86OutputPtr output)
{
}
static void
MSMOutputSave(xf86OutputPtr output)
{
}
static void
MSMOutputRestore(xf86OutputPtr output)
{
}
static int
MSMOutputModeValid(xf86OutputPtr output, DisplayModePtr pMode)
{
return MODE_OK;
}
static Bool
MSMOutputModeFixup(xf86OutputPtr output, DisplayModePtr mode,
DisplayModePtr adjmode)
{
return TRUE;
}
static void
MSMOutputModeSet(xf86OutputPtr output, DisplayModePtr mode,
DisplayModePtr adjmode)
{
/* Nothing to do on the output side */
}
static xf86OutputStatus
MSMOutputDetect(xf86OutputPtr output)
{
return XF86OutputStatusConnected;
}
static DisplayModePtr
MSMOutputGetModes(xf86OutputPtr output)
{
ScrnInfoPtr pScrn = output->scrn;
MSMPtr pMsm = MSMPTR(pScrn);
DisplayModePtr modes = NULL;
modes = xf86DuplicateMode(&pMsm->default_mode);
return modes;
}
static void
MSMOutputDestroy(xf86OutputPtr output)
{
}
static const xf86OutputFuncsRec MSMOutputFuncs = {
.create_resources = MSMOutputCreateResources,
.dpms = MSMOutputDPMS,
.save = MSMOutputSave,
.restore = MSMOutputRestore,
.mode_valid = MSMOutputModeValid,
.mode_fixup = MSMOutputModeFixup,
.prepare = MSMOutputPrepare,
.mode_set = MSMOutputModeSet,
.commit = MSMOutputCommit,
.detect = MSMOutputDetect,
.get_modes = MSMOutputGetModes,
.set_property = MSMOutputSetProperty,
.destroy = MSMOutputDestroy
};
void
MSMOutputSetup(ScrnInfoPtr pScrn)
{
xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
xf86OutputPtr output;
/*For primary display*/
output = xf86OutputCreate(pScrn, &MSMOutputFuncs, "default");
output->interlaceAllowed = FALSE;
output->doubleScanAllowed = FALSE;
/* FIXME: Set monitor size here? */
output->possible_crtcs = 1;
output->driver_private = NULL;
output->crtc = xf86_config->crtc[0];
}

135
src/msm-pixmap.c Normal file
View File

@@ -0,0 +1,135 @@
/* msm-pixmap.c
*
* Copyright (c) 2009 - 2010 Code Aurora Forum. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of Code Aurora nor
* the names of its contributors may be used to endorse or promote
* products derived from this software without specific prior written
* permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "msm.h"
#include "msm-drm.h"
unsigned int
msm_pixmap_gpuptr(PixmapPtr pixmap)
{
ScreenPtr pScreen = pixmap->drawable.pScreen;
MSMPtr pMsm = MSMPTR_FROM_PIXMAP(pixmap);
if (msm_pixmap_in_gem(pixmap)) {
struct msm_drm_bo *bo = msm_get_pixmap_bo(pixmap);
if (!msm_drm_bo_bind_gpu(bo)) {
return (unsigned int) bo->gpuaddr[bo->active];
}
}
/* Return the physical address of the framebuffer */
/* If we have a BO for the framebuffer, then bind it
and return the adress, otherwise revert back to the
physical address */
if ((pScreen->GetScreenPixmap(pScreen) == pixmap) ||
(pMsm->rotatedPixmap == pixmap)) {
unsigned int offset = 0;
if(pMsm->rotatedPixmap == pixmap)
offset = pMsm->mode_info.yres * pMsm->fixed_info.line_length;
if (pMsm->fbBo && !msm_drm_bo_bind_gpu(pMsm->fbBo))
return (unsigned int) (pMsm->fbBo->gpuaddr[0] + offset);
return ((unsigned int)pMsm->fixed_info.smem_start + offset);
}
return 0;
}
void *
msm_pixmap_hostptr(PixmapPtr pixmap)
{
ScreenPtr pScreen = pixmap->drawable.pScreen;
MSMPtr pMsm = MSMPTR_FROM_PIXMAP(pixmap);
if (msm_pixmap_in_gem(pixmap)) {
struct msm_drm_bo *bo = msm_get_pixmap_bo(pixmap);
return (void *) bo->virtaddr[bo->active];
}
/* Return virtual address of the framebuffer */
if (pScreen->GetScreenPixmap(pScreen) == pixmap)
return pMsm->curVisiblePtr;
return (void *) pixmap->devPrivate.ptr;
}
int
msm_pixmap_offset(PixmapPtr pixmap)
{
return 0;
}
int
msm_pixmap_get_pitch(PixmapPtr pix)
{
struct msm_pixmap_priv *priv = exaGetPixmapDriverPrivate(pix);
/* We only modify the pitch for 16bpp operations */
if (priv && priv->bo && pix->drawable.bitsPerPixel == 16) {
return ((pix->drawable.width + 31) & ~31) *
(pix->drawable.bitsPerPixel >> 3);
}
return exaGetPixmapPitch(pix);
}
Bool
msm_pixmap_in_gem(PixmapPtr pix)
{
struct msm_pixmap_priv *priv = exaGetPixmapDriverPrivate(pix);
if (priv && priv->bo)
return TRUE;
return FALSE;
}
struct msm_drm_bo *
msm_get_pixmap_bo(PixmapPtr pix)
{
struct msm_pixmap_priv *priv = exaGetPixmapDriverPrivate(pix);
if (priv && priv->bo) {
/* When this fucntion is called then ensure it gets
allocated - if this function ever gets used outside of
EXA this could cause problems */
msm_drm_bo_alloc(priv->bo);
return priv->bo;
}
return NULL;
}

169
src/msm.h Normal file
View File

@@ -0,0 +1,169 @@
/* msm.h
*
* Copyright (c) 2009-2010 Code Aurora Forum. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of Code Aurora nor
* the names of its contributors may be used to endorse or promote
* products derived from this software without specific prior written
* permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _MSM_H_
#define _MSM_H_
#include "xf86.h"
#include "damage.h"
#include "exa.h"
#include <linux/fb.h>
#include <linux/ioctl.h>
#include <linux/msm_mdp.h>
#define ARRAY_SIZE(a) (sizeof((a)) / (sizeof(*(a))))
/* This enumerates all of the available options */
typedef enum
{
OPTION_FB,
OPTION_NOACCEL,
OPTION_SWCURSOR,
OPTION_VSYNC,
OPTION_FBCACHE,
OPTION_PIXMAP_MEMTYPE,
OPTION_PAGEFLIP,
OPTION_DRIMEMTYPE,
OPTION_DEBUG,
} MSMOpts;
typedef enum
{
MSM_MDP_VERSION_22,
MSM_MDP_VERSION_31,
MSM_MDP_VERSION_40,
} MSMChipType;
typedef struct _MSMRec
{
/* File descriptor for the framebuffer device */
int fd;
/* Fixed and var strutures from the framebuffer */
struct fb_fix_screeninfo fixed_info;
struct fb_var_screeninfo mode_info;
/* Pointer to the mapped framebuffer memory */
void *fbmem;
/* Processor identifier */
MSMChipType chipID;
/* Default mode for X */
DisplayModeRec default_mode;
/* EXA driver structure */
ExaDriverPtr pExa;
/* Place holder for the standard close screen function */
CloseScreenProcPtr CloseScreen;
Bool HWCursor;
int HWCursorState;
int defaultVsync;
int FBCache;
int drmFD;
char drmDevName[64];
int pixmapMemtype;
int DRIMemtype;
struct msm_drm_bo *cachedBo;
struct msm_drm_bo *fbBo;
void *curVisiblePtr;
OptionInfoPtr options;
PixmapPtr rotatedPixmap;
Bool isFBSurfaceStale;
PictTransform *currentTransform;
} MSMRec, *MSMPtr;
struct msm_pixmap_priv {
struct msm_drm_bo *bo;
int SavedPitch;
unsigned int c2dsurface;
};
/* Macro to get the private record from the ScreenInfo structure */
#define MSMPTR(p) ((MSMPtr) ((p)->driverPrivate))
#define MSMPTR_FROM_PIXMAP(_x) \
MSMPTR(xf86Screens[(_x)->drawable.pScreen->myNum])
Bool MSMSetupExa(ScreenPtr);
void MSMSetCursorPosition(MSMPtr pMsm, int x, int y);
void MSMCursorEnable(MSMPtr pMsm, Bool enable);
void MSMCursorLoadARGB(MSMPtr pMsm, CARD32 * image);
Bool MSMCursorInit(ScreenPtr pScreen);
void MSMOutputSetup(ScrnInfoPtr pScrn);
void MSMCrtcSetup(ScrnInfoPtr pScrn);
#define MSM_OFFSCREEN_GEM 0x01
#define xFixedtoDouble(_f) (double) ((_f)/(double) xFixed1)
unsigned int msm_pixmap_gpuptr(PixmapPtr);
void *msm_pixmap_hostptr(PixmapPtr);
int msm_pixmap_offset(PixmapPtr);
int msm_pixmap_get_pitch(PixmapPtr pix);
Bool msm_pixmap_in_gem(PixmapPtr);
struct msm_drm_bo *msm_get_pixmap_bo(PixmapPtr);
/**
* This controls whether debug statements (and function "trace" enter/exit)
* messages are sent to the log file (TRUE) or are ignored (FALSE).
*/
extern Bool msmDebug;
/* Various logging/debug macros for use in the X driver and the external
* sub-modules:
*/
#define DEBUG_MSG(fmt, ...) \
do { if (msmDebug) 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 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)
#endif

View File

@@ -0,0 +1,192 @@
#ifndef _KGSL_DRM_H_
#define _KGSL_DRM_H_
#include "drm.h"
#define DRM_KGSL_GEM_CREATE 0x00
#define DRM_KGSL_GEM_PREP 0x01
#define DRM_KGSL_GEM_SETMEMTYPE 0x02
#define DRM_KGSL_GEM_GETMEMTYPE 0x03
#define DRM_KGSL_GEM_MMAP 0x04
#define DRM_KGSL_GEM_ALLOC 0x05
#define DRM_KGSL_GEM_BIND_GPU 0x06
#define DRM_KGSL_GEM_UNBIND_GPU 0x07
#define DRM_KGSL_GEM_GET_BUFINFO 0x08
#define DRM_KGSL_GEM_SET_BUFCOUNT 0x09
#define DRM_KGSL_GEM_SET_ACTIVE 0x0A
#define DRM_KGSL_GEM_LOCK_HANDLE 0x0B
#define DRM_KGSL_GEM_UNLOCK_HANDLE 0x0C
#define DRM_KGSL_GEM_UNLOCK_ON_TS 0x0D
#define DRM_KGSL_GEM_CREATE_FD 0x0E
#define DRM_IOCTL_KGSL_GEM_CREATE \
DRM_IOWR(DRM_COMMAND_BASE + DRM_KGSL_GEM_CREATE, struct drm_kgsl_gem_create)
#define DRM_IOCTL_KGSL_GEM_PREP \
DRM_IOWR(DRM_COMMAND_BASE + DRM_KGSL_GEM_PREP, struct drm_kgsl_gem_prep)
#define DRM_IOCTL_KGSL_GEM_SETMEMTYPE \
DRM_IOWR(DRM_COMMAND_BASE + DRM_KGSL_GEM_SETMEMTYPE, \
struct drm_kgsl_gem_memtype)
#define DRM_IOCTL_KGSL_GEM_GETMEMTYPE \
DRM_IOWR(DRM_COMMAND_BASE + DRM_KGSL_GEM_GETMEMTYPE, \
struct drm_kgsl_gem_memtype)
#define DRM_IOCTL_KGSL_GEM_MMAP \
DRM_IOWR(DRM_COMMAND_BASE + DRM_KGSL_GEM_MMAP, struct drm_kgsl_gem_mmap)
#define DRM_IOCTL_KGSL_GEM_ALLOC \
DRM_IOWR(DRM_COMMAND_BASE + DRM_KGSL_GEM_ALLOC, struct drm_kgsl_gem_alloc)
#define DRM_IOCTL_KGSL_GEM_BIND_GPU \
DRM_IOWR(DRM_COMMAND_BASE + DRM_KGSL_GEM_BIND_GPU, struct drm_kgsl_gem_bind_gpu)
#define DRM_IOCTL_KGSL_GEM_UNBIND_GPU \
DRM_IOWR(DRM_COMMAND_BASE + DRM_KGSL_GEM_UNBIND_GPU, \
struct drm_kgsl_gem_bind_gpu)
#define DRM_IOCTL_KGSL_GEM_GET_BUFINFO \
DRM_IOWR(DRM_COMMAND_BASE + DRM_KGSL_GEM_GET_BUFINFO, \
struct drm_kgsl_gem_bufinfo)
#define DRM_IOCTL_KGSL_GEM_SET_BUFCOUNT \
DRM_IOWR(DRM_COMMAND_BASE + DRM_KGSL_GEM_SET_BUFCOUNT, \
struct drm_kgsl_gem_bufcount)
#define DRM_IOCTL_KGSL_GEM_SET_ACTIVE \
DRM_IOWR(DRM_COMMAND_BASE + DRM_KGSL_GEM_SET_ACTIVE, \
struct drm_kgsl_gem_active)
#define DRM_IOCTL_KGSL_GEM_LOCK_HANDLE \
DRM_IOWR(DRM_COMMAND_BASE + DRM_KGSL_GEM_LOCK_HANDLE, \
struct drm_kgsl_gem_lock_handles)
#define DRM_IOCTL_KGSL_GEM_UNLOCK_HANDLE \
DRM_IOWR(DRM_COMMAND_BASE + DRM_KGSL_GEM_UNLOCK_HANDLE, \
struct drm_kgsl_gem_unlock_handles)
#define DRM_IOCTL_KGSL_GEM_UNLOCK_ON_TS \
DRM_IOWR(DRM_COMMAND_BASE + DRM_KGSL_GEM_UNLOCK_ON_TS, \
struct drm_kgsl_gem_unlock_on_ts)
#define DRM_IOCTL_KGSL_GEM_CREATE_FD \
DRM_IOWR(DRM_COMMAND_BASE + DRM_KGSL_GEM_CREATE_FD, \
struct drm_kgsl_gem_create_fd)
/* Maximum number of sub buffers per GEM object */
#define DRM_KGSL_GEM_MAX_BUFFERS 2
/* Memory types - these define the source and caching policies
of the GEM memory chunk */
/* Legacy definitions left for compatability */
#define DRM_KGSL_GEM_TYPE_EBI 0
#define DRM_KGSL_GEM_TYPE_SMI 1
#define DRM_KGSL_GEM_TYPE_KMEM 2
#define DRM_KGSL_GEM_TYPE_KMEM_NOCACHE 3
#define DRM_KGSL_GEM_TYPE_MEM_MASK 0xF
/* Contiguous memory (PMEM) */
#define DRM_KGSL_GEM_TYPE_PMEM 0x000100
/* PMEM memory types */
#define DRM_KGSL_GEM_PMEM_EBI 0x001000
#define DRM_KGSL_GEM_PMEM_SMI 0x002000
/* Standard paged memory */
#define DRM_KGSL_GEM_TYPE_MEM 0x010000
/* Caching controls */
#define DRM_KGSL_GEM_CACHE_NONE 0x000000
#define DRM_KGSL_GEM_CACHE_WCOMBINE 0x100000
#define DRM_KGSL_GEM_CACHE_WTHROUGH 0x200000
#define DRM_KGSL_GEM_CACHE_WBACK 0x400000
#define DRM_KGSL_GEM_CACHE_WBACKWA 0x800000
#define DRM_KGSL_GEM_CACHE_MASK 0xF00000
/* FD based objects */
#define DRM_KGSL_GEM_TYPE_FD_FBMEM 0x1000000
#define DRM_KGSL_GEM_TYPE_FD_MASK 0xF000000
/* Timestamp types */
#define DRM_KGSL_GEM_TS_3D 0x00000430
#define DRM_KGSL_GEM_TS_2D 0x00000180
struct drm_kgsl_gem_create {
uint32_t size;
uint32_t handle;
};
struct drm_kgsl_gem_prep {
uint32_t handle;
uint32_t phys;
uint64_t offset;
};
struct drm_kgsl_gem_memtype {
uint32_t handle;
uint32_t type;
};
struct drm_kgsl_gem_mmap {
uint32_t handle;
uint32_t size;
uint32_t hostptr;
uint64_t offset;
};
struct drm_kgsl_gem_alloc {
uint32_t handle;
uint64_t offset;
};
struct drm_kgsl_gem_bind_gpu {
uint32_t handle;
uint32_t gpuptr;
};
struct drm_kgsl_gem_bufinfo {
uint32_t handle;
uint32_t count;
uint32_t active;
uint32_t offset[DRM_KGSL_GEM_MAX_BUFFERS];
uint32_t gpuaddr[DRM_KGSL_GEM_MAX_BUFFERS];
};
struct drm_kgsl_gem_bufcount {
uint32_t handle;
uint32_t bufcount;
};
struct drm_kgsl_gem_active {
uint32_t handle;
uint32_t active;
};
struct drm_kgsl_gem_lock_handles {
uint32_t num_handles;
uint32_t *handle_list;
uint32_t pid;
uint32_t lock_id; /* Returned lock id used for unlocking */
};
struct drm_kgsl_gem_unlock_handles {
uint32_t lock_id;
};
struct drm_kgsl_gem_unlock_on_ts {
uint32_t lock_id;
uint32_t timestamp; /* This field is a hw generated ts */
uint32_t type; /* Which pipe to check for ts generation */
};
struct drm_kgsl_gem_create_fd {
uint32_t fd;
uint32_t handle;
};
#endif

View File

@@ -0,0 +1,476 @@
#ifndef _MSM_KGSL_H
#define _MSM_KGSL_H
#define KGSL_VERSION_MAJOR 3
#define KGSL_VERSION_MINOR 8
/*context flags */
#define KGSL_CONTEXT_SAVE_GMEM 1
#define KGSL_CONTEXT_NO_GMEM_ALLOC 2
#define KGSL_CONTEXT_SUBMIT_IB_LIST 4
#define KGSL_CONTEXT_CTX_SWITCH 8
#define KGSL_CONTEXT_PREAMBLE 16
/* Memory allocayion flags */
#define KGSL_MEMFLAGS_GPUREADONLY 0x01000000
/* generic flag values */
#define KGSL_FLAGS_NORMALMODE 0x00000000
#define KGSL_FLAGS_SAFEMODE 0x00000001
#define KGSL_FLAGS_INITIALIZED0 0x00000002
#define KGSL_FLAGS_INITIALIZED 0x00000004
#define KGSL_FLAGS_STARTED 0x00000008
#define KGSL_FLAGS_ACTIVE 0x00000010
#define KGSL_FLAGS_RESERVED0 0x00000020
#define KGSL_FLAGS_RESERVED1 0x00000040
#define KGSL_FLAGS_RESERVED2 0x00000080
#define KGSL_FLAGS_SOFT_RESET 0x00000100
/* Clock flags to show which clocks should be controled by a given platform */
#define KGSL_CLK_SRC 0x00000001
#define KGSL_CLK_CORE 0x00000002
#define KGSL_CLK_IFACE 0x00000004
#define KGSL_CLK_MEM 0x00000008
#define KGSL_CLK_MEM_IFACE 0x00000010
#define KGSL_CLK_AXI 0x00000020
/*
* Reset status values for context
*/
enum kgsl_ctx_reset_stat {
KGSL_CTX_STAT_NO_ERROR = 0x00000000,
KGSL_CTX_STAT_GUILTY_CONTEXT_RESET_EXT = 0x00000001,
KGSL_CTX_STAT_INNOCENT_CONTEXT_RESET_EXT = 0x00000002,
KGSL_CTX_STAT_UNKNOWN_CONTEXT_RESET_EXT = 0x00000003
};
#define KGSL_MAX_PWRLEVELS 5
#define KGSL_CONVERT_TO_MBPS(val) \
(val*1000*1000U)
/* device id */
enum kgsl_deviceid {
KGSL_DEVICE_3D0 = 0x00000000,
KGSL_DEVICE_2D0 = 0x00000001,
KGSL_DEVICE_2D1 = 0x00000002,
KGSL_DEVICE_MAX = 0x00000003
};
enum kgsl_user_mem_type {
KGSL_USER_MEM_TYPE_PMEM = 0x00000000,
KGSL_USER_MEM_TYPE_ASHMEM = 0x00000001,
KGSL_USER_MEM_TYPE_ADDR = 0x00000002,
KGSL_USER_MEM_TYPE_ION = 0x00000003,
KGSL_USER_MEM_TYPE_MAX = 0x00000004,
};
struct kgsl_devinfo {
unsigned int device_id;
/* chip revision id
* coreid:8 majorrev:8 minorrev:8 patch:8
*/
unsigned int chip_id;
unsigned int mmu_enabled;
unsigned int gmem_gpubaseaddr;
/*
* This field contains the adreno revision
* number 200, 205, 220, etc...
*/
unsigned int gpu_id;
unsigned int gmem_sizebytes;
};
/* this structure defines the region of memory that can be mmap()ed from this
driver. The timestamp fields are volatile because they are written by the
GPU
*/
struct kgsl_devmemstore {
volatile unsigned int soptimestamp;
unsigned int sbz;
volatile unsigned int eoptimestamp;
unsigned int sbz2;
volatile unsigned int ts_cmp_enable;
unsigned int sbz3;
volatile unsigned int ref_wait_ts;
unsigned int sbz4;
unsigned int current_context;
unsigned int sbz5;
};
#define KGSL_DEVICE_MEMSTORE_OFFSET(field) \
offsetof(struct kgsl_devmemstore, field)
/* timestamp id*/
enum kgsl_timestamp_type {
KGSL_TIMESTAMP_CONSUMED = 0x00000001, /* start-of-pipeline timestamp */
KGSL_TIMESTAMP_RETIRED = 0x00000002, /* end-of-pipeline timestamp*/
KGSL_TIMESTAMP_MAX = 0x00000002,
};
/* property types - used with kgsl_device_getproperty */
enum kgsl_property_type {
KGSL_PROP_DEVICE_INFO = 0x00000001,
KGSL_PROP_DEVICE_SHADOW = 0x00000002,
KGSL_PROP_DEVICE_POWER = 0x00000003,
KGSL_PROP_SHMEM = 0x00000004,
KGSL_PROP_SHMEM_APERTURES = 0x00000005,
KGSL_PROP_MMU_ENABLE = 0x00000006,
KGSL_PROP_INTERRUPT_WAITS = 0x00000007,
KGSL_PROP_VERSION = 0x00000008,
KGSL_PROP_GPU_RESET_STAT = 0x00000009
};
struct kgsl_shadowprop {
unsigned int gpuaddr;
unsigned int size;
unsigned int flags; /* contains KGSL_FLAGS_ values */
};
struct kgsl_pwrlevel {
unsigned int gpu_freq;
unsigned int bus_freq;
unsigned int io_fraction;
};
struct kgsl_version {
unsigned int drv_major;
unsigned int drv_minor;
unsigned int dev_major;
unsigned int dev_minor;
};
#ifdef __KERNEL__
#define KGSL_3D0_REG_MEMORY "kgsl_3d0_reg_memory"
#define KGSL_3D0_IRQ "kgsl_3d0_irq"
#define KGSL_2D0_REG_MEMORY "kgsl_2d0_reg_memory"
#define KGSL_2D0_IRQ "kgsl_2d0_irq"
#define KGSL_2D1_REG_MEMORY "kgsl_2d1_reg_memory"
#define KGSL_2D1_IRQ "kgsl_2d1_irq"
struct kgsl_device_iommu_data {
const char **iommu_ctx_names;
int iommu_ctx_count;
unsigned int physstart;
unsigned int physend;
};
struct kgsl_device_platform_data {
struct kgsl_pwrlevel pwrlevel[KGSL_MAX_PWRLEVELS];
int init_level;
int num_levels;
int (*set_grp_async)(void);
unsigned int idle_timeout;
unsigned int nap_allowed;
unsigned int clk_map;
unsigned int idle_needed;
struct msm_bus_scale_pdata *bus_scale_table;
struct kgsl_device_iommu_data *iommu_data;
int iommu_count;
};
#endif
/* structure holds list of ibs */
struct kgsl_ibdesc {
unsigned int gpuaddr;
void *hostptr;
unsigned int sizedwords;
unsigned int ctrl;
};
/* ioctls */
#define KGSL_IOC_TYPE 0x09
/* get misc info about the GPU
type should be a value from enum kgsl_property_type
value points to a structure that varies based on type
sizebytes is sizeof() that structure
for KGSL_PROP_DEVICE_INFO, use struct kgsl_devinfo
this structure contaings hardware versioning info.
for KGSL_PROP_DEVICE_SHADOW, use struct kgsl_shadowprop
this is used to find mmap() offset and sizes for mapping
struct kgsl_memstore into userspace.
*/
struct kgsl_device_getproperty {
unsigned int type;
void *value;
unsigned int sizebytes;
};
#define IOCTL_KGSL_DEVICE_GETPROPERTY \
_IOWR(KGSL_IOC_TYPE, 0x2, struct kgsl_device_getproperty)
/* read a GPU register.
offsetwords it the 32 bit word offset from the beginning of the
GPU register space.
*/
struct kgsl_device_regread {
unsigned int offsetwords;
unsigned int value; /* output param */
};
#define IOCTL_KGSL_DEVICE_REGREAD \
_IOWR(KGSL_IOC_TYPE, 0x3, struct kgsl_device_regread)
/* block until the GPU has executed past a given timestamp
* timeout is in milliseconds.
*/
struct kgsl_device_waittimestamp {
unsigned int timestamp;
unsigned int timeout;
};
#define IOCTL_KGSL_DEVICE_WAITTIMESTAMP \
_IOW(KGSL_IOC_TYPE, 0x6, struct kgsl_device_waittimestamp)
/* issue indirect commands to the GPU.
* drawctxt_id must have been created with IOCTL_KGSL_DRAWCTXT_CREATE
* ibaddr and sizedwords must specify a subset of a buffer created
* with IOCTL_KGSL_SHAREDMEM_FROM_PMEM
* flags may be a mask of KGSL_CONTEXT_ values
* timestamp is a returned counter value which can be passed to
* other ioctls to determine when the commands have been executed by
* the GPU.
*/
struct kgsl_ringbuffer_issueibcmds {
unsigned int drawctxt_id;
unsigned int ibdesc_addr;
unsigned int numibs;
unsigned int timestamp; /*output param */
unsigned int flags;
};
#define IOCTL_KGSL_RINGBUFFER_ISSUEIBCMDS \
_IOWR(KGSL_IOC_TYPE, 0x10, struct kgsl_ringbuffer_issueibcmds)
/* read the most recently executed timestamp value
* type should be a value from enum kgsl_timestamp_type
*/
struct kgsl_cmdstream_readtimestamp {
unsigned int type;
unsigned int timestamp; /*output param */
};
#define IOCTL_KGSL_CMDSTREAM_READTIMESTAMP_OLD \
_IOR(KGSL_IOC_TYPE, 0x11, struct kgsl_cmdstream_readtimestamp)
#define IOCTL_KGSL_CMDSTREAM_READTIMESTAMP \
_IOWR(KGSL_IOC_TYPE, 0x11, struct kgsl_cmdstream_readtimestamp)
/* free memory when the GPU reaches a given timestamp.
* gpuaddr specify a memory region created by a
* IOCTL_KGSL_SHAREDMEM_FROM_PMEM call
* type should be a value from enum kgsl_timestamp_type
*/
struct kgsl_cmdstream_freememontimestamp {
unsigned int gpuaddr;
unsigned int type;
unsigned int timestamp;
};
#define IOCTL_KGSL_CMDSTREAM_FREEMEMONTIMESTAMP \
_IOW(KGSL_IOC_TYPE, 0x12, struct kgsl_cmdstream_freememontimestamp)
/* Previous versions of this header had incorrectly defined
IOCTL_KGSL_CMDSTREAM_FREEMEMONTIMESTAMP as a read-only ioctl instead
of a write only ioctl. To ensure binary compatability, the following
#define will be used to intercept the incorrect ioctl
*/
#define IOCTL_KGSL_CMDSTREAM_FREEMEMONTIMESTAMP_OLD \
_IOR(KGSL_IOC_TYPE, 0x12, struct kgsl_cmdstream_freememontimestamp)
/* create a draw context, which is used to preserve GPU state.
* The flags field may contain a mask KGSL_CONTEXT_* values
*/
struct kgsl_drawctxt_create {
unsigned int flags;
unsigned int drawctxt_id; /*output param */
};
#define IOCTL_KGSL_DRAWCTXT_CREATE \
_IOWR(KGSL_IOC_TYPE, 0x13, struct kgsl_drawctxt_create)
/* destroy a draw context */
struct kgsl_drawctxt_destroy {
unsigned int drawctxt_id;
};
#define IOCTL_KGSL_DRAWCTXT_DESTROY \
_IOW(KGSL_IOC_TYPE, 0x14, struct kgsl_drawctxt_destroy)
/* add a block of pmem, fb, ashmem or user allocated address
* into the GPU address space */
struct kgsl_map_user_mem {
int fd;
unsigned int gpuaddr; /*output param */
unsigned int len;
unsigned int offset;
unsigned int hostptr; /*input param */
enum kgsl_user_mem_type memtype;
unsigned int reserved; /* May be required to add
params for another mem type */
};
#define IOCTL_KGSL_MAP_USER_MEM \
_IOWR(KGSL_IOC_TYPE, 0x15, struct kgsl_map_user_mem)
/* add a block of pmem or fb into the GPU address space */
struct kgsl_sharedmem_from_pmem {
int pmem_fd;
unsigned int gpuaddr; /*output param */
unsigned int len;
unsigned int offset;
};
#define IOCTL_KGSL_SHAREDMEM_FROM_PMEM \
_IOWR(KGSL_IOC_TYPE, 0x20, struct kgsl_sharedmem_from_pmem)
/* remove memory from the GPU's address space */
struct kgsl_sharedmem_free {
unsigned int gpuaddr;
};
#define IOCTL_KGSL_SHAREDMEM_FREE \
_IOW(KGSL_IOC_TYPE, 0x21, struct kgsl_sharedmem_free)
struct kgsl_cff_user_event {
unsigned char cff_opcode;
unsigned int op1;
unsigned int op2;
unsigned int op3;
unsigned int op4;
unsigned int op5;
unsigned int __pad[2];
};
#define IOCTL_KGSL_CFF_USER_EVENT \
_IOW(KGSL_IOC_TYPE, 0x31, struct kgsl_cff_user_event)
struct kgsl_gmem_desc {
unsigned int x;
unsigned int y;
unsigned int width;
unsigned int height;
unsigned int pitch;
};
struct kgsl_buffer_desc {
void *hostptr;
unsigned int gpuaddr;
int size;
unsigned int format;
unsigned int pitch;
unsigned int enabled;
};
struct kgsl_bind_gmem_shadow {
unsigned int drawctxt_id;
struct kgsl_gmem_desc gmem_desc;
unsigned int shadow_x;
unsigned int shadow_y;
struct kgsl_buffer_desc shadow_buffer;
unsigned int buffer_id;
};
#define IOCTL_KGSL_DRAWCTXT_BIND_GMEM_SHADOW \
_IOW(KGSL_IOC_TYPE, 0x22, struct kgsl_bind_gmem_shadow)
/* add a block of memory into the GPU address space */
struct kgsl_sharedmem_from_vmalloc {
unsigned int gpuaddr; /*output param */
unsigned int hostptr;
unsigned int flags;
};
#define IOCTL_KGSL_SHAREDMEM_FROM_VMALLOC \
_IOWR(KGSL_IOC_TYPE, 0x23, struct kgsl_sharedmem_from_vmalloc)
#define IOCTL_KGSL_SHAREDMEM_FLUSH_CACHE \
_IOW(KGSL_IOC_TYPE, 0x24, struct kgsl_sharedmem_free)
struct kgsl_drawctxt_set_bin_base_offset {
unsigned int drawctxt_id;
unsigned int offset;
};
#define IOCTL_KGSL_DRAWCTXT_SET_BIN_BASE_OFFSET \
_IOW(KGSL_IOC_TYPE, 0x25, struct kgsl_drawctxt_set_bin_base_offset)
enum kgsl_cmdwindow_type {
KGSL_CMDWINDOW_MIN = 0x00000000,
KGSL_CMDWINDOW_2D = 0x00000000,
KGSL_CMDWINDOW_3D = 0x00000001, /* legacy */
KGSL_CMDWINDOW_MMU = 0x00000002,
KGSL_CMDWINDOW_ARBITER = 0x000000FF,
KGSL_CMDWINDOW_MAX = 0x000000FF,
};
/* write to the command window */
struct kgsl_cmdwindow_write {
enum kgsl_cmdwindow_type target;
unsigned int addr;
unsigned int data;
};
#define IOCTL_KGSL_CMDWINDOW_WRITE \
_IOW(KGSL_IOC_TYPE, 0x2e, struct kgsl_cmdwindow_write)
struct kgsl_gpumem_alloc {
unsigned long gpuaddr;
size_t size;
unsigned int flags;
};
#define IOCTL_KGSL_GPUMEM_ALLOC \
_IOWR(KGSL_IOC_TYPE, 0x2f, struct kgsl_gpumem_alloc)
struct kgsl_cff_syncmem {
unsigned int gpuaddr;
unsigned int len;
unsigned int __pad[2]; /* For future binary compatibility */
};
#define IOCTL_KGSL_CFF_SYNCMEM \
_IOW(KGSL_IOC_TYPE, 0x30, struct kgsl_cff_syncmem)
/*
* A timestamp event allows the user space to register an action following an
* expired timestamp.
*/
struct kgsl_timestamp_event {
int type; /* Type of event (see list below) */
unsigned int timestamp; /* Timestamp to trigger event on */
unsigned int context_id; /* Context for the timestamp */
void *priv; /* Pointer to the event specific blob */
size_t len; /* Size of the event specific blob */
};
#define IOCTL_KGSL_TIMESTAMP_EVENT \
_IOW(KGSL_IOC_TYPE, 0x31, struct kgsl_timestamp_event)
/* A genlock timestamp event releases an existing lock on timestamp expire */
#define KGSL_TIMESTAMP_EVENT_GENLOCK 1
struct kgsl_timestamp_event_genlock {
int handle; /* Handle of the genlock lock to release */
};
#ifdef __KERNEL__
#ifdef CONFIG_MSM_KGSL_DRM
int kgsl_gem_obj_addr(int drm_fd, int handle, unsigned long *start,
unsigned long *len);
#else
#define kgsl_gem_obj_addr(...) 0
#endif
#endif
#endif /* _MSM_KGSL_H */

View File

@@ -0,0 +1,464 @@
/* include/linux/msm_mdp.h
*
* Copyright (C) 2007 Google Incorporated
* Copyright (c) 2012 Code Aurora Forum. All rights reserved.
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
* may be copied, distributed, and modified under those terms.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#ifndef _MSM_MDP_H_
#define _MSM_MDP_H_
#include <linux/types.h>
#include <linux/fb.h>
#define MSMFB_IOCTL_MAGIC 'm'
#define MSMFB_GRP_DISP _IOW(MSMFB_IOCTL_MAGIC, 1, unsigned int)
#define MSMFB_BLIT _IOW(MSMFB_IOCTL_MAGIC, 2, unsigned int)
#define MSMFB_SUSPEND_SW_REFRESHER _IOW(MSMFB_IOCTL_MAGIC, 128, unsigned int)
#define MSMFB_RESUME_SW_REFRESHER _IOW(MSMFB_IOCTL_MAGIC, 129, unsigned int)
#define MSMFB_CURSOR _IOW(MSMFB_IOCTL_MAGIC, 130, struct fb_cursor)
#define MSMFB_SET_LUT _IOW(MSMFB_IOCTL_MAGIC, 131, struct fb_cmap)
#define MSMFB_HISTOGRAM _IOWR(MSMFB_IOCTL_MAGIC, 132, struct mdp_histogram)
/* new ioctls's for set/get ccs matrix */
#define MSMFB_GET_CCS_MATRIX _IOWR(MSMFB_IOCTL_MAGIC, 133, struct mdp_ccs)
#define MSMFB_SET_CCS_MATRIX _IOW(MSMFB_IOCTL_MAGIC, 134, struct mdp_ccs)
#define MSMFB_OVERLAY_SET _IOWR(MSMFB_IOCTL_MAGIC, 135, \
struct mdp_overlay)
#define MSMFB_OVERLAY_UNSET _IOW(MSMFB_IOCTL_MAGIC, 136, unsigned int)
#define MSMFB_OVERLAY_PLAY _IOW(MSMFB_IOCTL_MAGIC, 137, \
struct msmfb_overlay_data)
#define MSMFB_GET_PAGE_PROTECTION _IOR(MSMFB_IOCTL_MAGIC, 138, \
struct mdp_page_protection)
#define MSMFB_SET_PAGE_PROTECTION _IOW(MSMFB_IOCTL_MAGIC, 139, \
struct mdp_page_protection)
#define MSMFB_OVERLAY_GET _IOR(MSMFB_IOCTL_MAGIC, 140, \
struct mdp_overlay)
#define MSMFB_OVERLAY_PLAY_ENABLE _IOW(MSMFB_IOCTL_MAGIC, 141, unsigned int)
#define MSMFB_OVERLAY_BLT _IOWR(MSMFB_IOCTL_MAGIC, 142, \
struct msmfb_overlay_blt)
#define MSMFB_OVERLAY_BLT_OFFSET _IOW(MSMFB_IOCTL_MAGIC, 143, unsigned int)
#define MSMFB_HISTOGRAM_START _IO(MSMFB_IOCTL_MAGIC, 144)
#define MSMFB_HISTOGRAM_STOP _IO(MSMFB_IOCTL_MAGIC, 145)
#define MSMFB_NOTIFY_UPDATE _IOW(MSMFB_IOCTL_MAGIC, 146, unsigned int)
#define MSMFB_OVERLAY_3D _IOWR(MSMFB_IOCTL_MAGIC, 147, \
struct msmfb_overlay_3d)
#define MSMFB_MIXER_INFO _IOWR(MSMFB_IOCTL_MAGIC, 148, \
struct msmfb_mixer_info_req)
#define MSMFB_OVERLAY_PLAY_WAIT _IOWR(MSMFB_IOCTL_MAGIC, 149, \
struct msmfb_overlay_data)
#define MSMFB_WRITEBACK_INIT _IO(MSMFB_IOCTL_MAGIC, 150)
#define MSMFB_WRITEBACK_START _IO(MSMFB_IOCTL_MAGIC, 151)
#define MSMFB_WRITEBACK_STOP _IO(MSMFB_IOCTL_MAGIC, 152)
#define MSMFB_WRITEBACK_QUEUE_BUFFER _IOW(MSMFB_IOCTL_MAGIC, 153, \
struct msmfb_data)
#define MSMFB_WRITEBACK_DEQUEUE_BUFFER _IOW(MSMFB_IOCTL_MAGIC, 154, \
struct msmfb_data)
#define MSMFB_WRITEBACK_TERMINATE _IO(MSMFB_IOCTL_MAGIC, 155)
#define MSMFB_MDP_PP _IOWR(MSMFB_IOCTL_MAGIC, 156, struct msmfb_mdp_pp)
#define FB_TYPE_3D_PANEL 0x10101010
#define MDP_IMGTYPE2_START 0x10000
#define MSMFB_DRIVER_VERSION 0xF9E8D701
enum {
NOTIFY_UPDATE_START,
NOTIFY_UPDATE_STOP,
};
enum {
MDP_RGB_565, /* RGB 565 planer */
MDP_XRGB_8888, /* RGB 888 padded */
MDP_Y_CBCR_H2V2, /* Y and CbCr, pseudo planer w/ Cb is in MSB */
MDP_Y_CBCR_H2V2_ADRENO,
MDP_ARGB_8888, /* ARGB 888 */
MDP_RGB_888, /* RGB 888 planer */
MDP_Y_CRCB_H2V2, /* Y and CrCb, pseudo planer w/ Cr is in MSB */
MDP_YCRYCB_H2V1, /* YCrYCb interleave */
MDP_Y_CRCB_H2V1, /* Y and CrCb, pseduo planer w/ Cr is in MSB */
MDP_Y_CBCR_H2V1, /* Y and CrCb, pseduo planer w/ Cr is in MSB */
MDP_RGBA_8888, /* ARGB 888 */
MDP_BGRA_8888, /* ABGR 888 */
MDP_RGBX_8888, /* RGBX 888 */
MDP_Y_CRCB_H2V2_TILE, /* Y and CrCb, pseudo planer tile */
MDP_Y_CBCR_H2V2_TILE, /* Y and CbCr, pseudo planer tile */
MDP_Y_CR_CB_H2V2, /* Y, Cr and Cb, planar */
MDP_Y_CR_CB_GH2V2, /* Y, Cr and Cb, planar aligned to Android YV12 */
MDP_Y_CB_CR_H2V2, /* Y, Cb and Cr, planar */
MDP_Y_CRCB_H1V1, /* Y and CrCb, pseduo planer w/ Cr is in MSB */
MDP_Y_CBCR_H1V1, /* Y and CbCr, pseduo planer w/ Cb is in MSB */
MDP_IMGTYPE_LIMIT,
MDP_BGR_565 = MDP_IMGTYPE2_START, /* BGR 565 planer */
MDP_FB_FORMAT, /* framebuffer format */
MDP_IMGTYPE_LIMIT2 /* Non valid image type after this enum */
};
enum {
PMEM_IMG,
FB_IMG,
};
enum {
HSIC_HUE = 0,
HSIC_SAT,
HSIC_INT,
HSIC_CON,
NUM_HSIC_PARAM,
};
/* mdp_blit_req flag values */
#define MDP_ROT_NOP 0
#define MDP_FLIP_LR 0x1
#define MDP_FLIP_UD 0x2
#define MDP_ROT_90 0x4
#define MDP_ROT_180 (MDP_FLIP_UD|MDP_FLIP_LR)
#define MDP_ROT_270 (MDP_ROT_90|MDP_FLIP_UD|MDP_FLIP_LR)
#define MDP_DITHER 0x8
#define MDP_BLUR 0x10
#define MDP_BLEND_FG_PREMULT 0x20000
#define MDP_DEINTERLACE 0x80000000
#define MDP_SHARPENING 0x40000000
#define MDP_NO_DMA_BARRIER_START 0x20000000
#define MDP_NO_DMA_BARRIER_END 0x10000000
#define MDP_NO_BLIT 0x08000000
#define MDP_BLIT_WITH_DMA_BARRIERS 0x000
#define MDP_BLIT_WITH_NO_DMA_BARRIERS \
(MDP_NO_DMA_BARRIER_START | MDP_NO_DMA_BARRIER_END)
#define MDP_BLIT_SRC_GEM 0x04000000
#define MDP_BLIT_DST_GEM 0x02000000
#define MDP_BLIT_NON_CACHED 0x01000000
#define MDP_OV_PIPE_SHARE 0x00800000
#define MDP_DEINTERLACE_ODD 0x00400000
#define MDP_OV_PLAY_NOWAIT 0x00200000
#define MDP_SOURCE_ROTATED_90 0x00100000
#define MDP_DPP_HSIC 0x00080000
#define MDP_BACKEND_COMPOSITION 0x00040000
#define MDP_BORDERFILL_SUPPORTED 0x00010000
#define MDP_SECURE_OVERLAY_SESSION 0x00008000
#define MDP_MEMORY_ID_TYPE_FB 0x00001000
#define MDP_TRANSP_NOP 0xffffffff
#define MDP_ALPHA_NOP 0xff
#define MDP_FB_PAGE_PROTECTION_NONCACHED (0)
#define MDP_FB_PAGE_PROTECTION_WRITECOMBINE (1)
#define MDP_FB_PAGE_PROTECTION_WRITETHROUGHCACHE (2)
#define MDP_FB_PAGE_PROTECTION_WRITEBACKCACHE (3)
#define MDP_FB_PAGE_PROTECTION_WRITEBACKWACACHE (4)
/* Sentinel: Don't use! */
#define MDP_FB_PAGE_PROTECTION_INVALID (5)
/* Count of the number of MDP_FB_PAGE_PROTECTION_... values. */
#define MDP_NUM_FB_PAGE_PROTECTION_VALUES (5)
struct mdp_rect {
uint32_t x;
uint32_t y;
uint32_t w;
uint32_t h;
};
struct mdp_img {
uint32_t width;
uint32_t height;
uint32_t format;
uint32_t offset;
int memory_id; /* the file descriptor */
uint32_t priv;
};
/*
* {3x3} + {3} ccs matrix
*/
#define MDP_CCS_RGB2YUV 0
#define MDP_CCS_YUV2RGB 1
#define MDP_CCS_SIZE 9
#define MDP_BV_SIZE 3
struct mdp_ccs {
int direction; /* MDP_CCS_RGB2YUV or YUV2RGB */
uint16_t ccs[MDP_CCS_SIZE]; /* 3x3 color coefficients */
uint16_t bv[MDP_BV_SIZE]; /* 1x3 bias vector */
};
struct mdp_csc {
int id;
uint32_t csc_mv[9];
uint32_t csc_pre_bv[3];
uint32_t csc_post_bv[3];
uint32_t csc_pre_lv[6];
uint32_t csc_post_lv[6];
};
/* The version of the mdp_blit_req structure so that
* user applications can selectively decide which functionality
* to include
*/
#define MDP_BLIT_REQ_VERSION 2
struct mdp_blit_req {
struct mdp_img src;
struct mdp_img dst;
struct mdp_rect src_rect;
struct mdp_rect dst_rect;
uint32_t alpha;
uint32_t transp_mask;
uint32_t flags;
int sharpening_strength; /* -127 <--> 127, default 64 */
};
struct mdp_blit_req_list {
uint32_t count;
struct mdp_blit_req req[];
};
#define MSMFB_DATA_VERSION 2
struct msmfb_data {
uint32_t offset;
int memory_id;
int id;
uint32_t flags;
uint32_t priv;
uint32_t iova;
};
#define MSMFB_NEW_REQUEST -1
struct msmfb_overlay_data {
uint32_t id;
struct msmfb_data data;
uint32_t version_key;
struct msmfb_data plane1_data;
struct msmfb_data plane2_data;
};
struct msmfb_img {
uint32_t width;
uint32_t height;
uint32_t format;
};
#define MSMFB_WRITEBACK_DEQUEUE_BLOCKING 0x1
struct msmfb_writeback_data {
struct msmfb_data buf_info;
struct msmfb_img img;
};
struct dpp_ctrl {
/*
*'sharp_strength' has inputs = -128 <-> 127
* Increasingly positive values correlate with increasingly sharper
* picture. Increasingly negative values correlate with increasingly
* smoothed picture.
*/
int8_t sharp_strength;
int8_t hsic_params[NUM_HSIC_PARAM];
};
struct mdp_overlay {
struct msmfb_img src;
struct mdp_rect src_rect;
struct mdp_rect dst_rect;
uint32_t z_order; /* stage number */
uint32_t is_fg; /* control alpha & transp */
uint32_t alpha;
uint32_t transp_mask;
uint32_t flags;
uint32_t id;
uint32_t user_data[8];
struct dpp_ctrl dpp;
};
struct msmfb_overlay_3d {
uint32_t is_3d;
uint32_t width;
uint32_t height;
};
struct msmfb_overlay_blt {
uint32_t enable;
uint32_t offset;
uint32_t width;
uint32_t height;
uint32_t bpp;
};
struct mdp_histogram {
uint32_t frame_cnt;
uint32_t bin_cnt;
uint32_t *r;
uint32_t *g;
uint32_t *b;
};
/*
mdp_block_type defines the identifiers for each of pipes in MDP 4.3
MDP_BLOCK_RESERVED is provided for backward compatibility and is
deprecated. It corresponds to DMA_P. So MDP_BLOCK_DMA_P should be used
instead.
*/
enum {
MDP_BLOCK_RESERVED = 0,
MDP_BLOCK_OVERLAY_0,
MDP_BLOCK_OVERLAY_1,
MDP_BLOCK_VG_1,
MDP_BLOCK_VG_2,
MDP_BLOCK_RGB_1,
MDP_BLOCK_RGB_2,
MDP_BLOCK_DMA_P,
MDP_BLOCK_DMA_S,
MDP_BLOCK_DMA_E,
MDP_BLOCK_MAX,
};
struct mdp_pcc_coeff {
uint32_t c, r, g, b, rr, gg, bb, rg, gb, rb, rgb_0, rgb_1;
};
struct mdp_pcc_cfg_data {
uint32_t block;
uint32_t ops;
struct mdp_pcc_coeff r, g, b;
};
#define MDP_CSC_FLAG_ENABLE 0x1
#define MDP_CSC_FLAG_YUV_IN 0x2
#define MDP_CSC_FLAG_YUV_OUT 0x4
struct mdp_csc_cfg {
/* flags for enable CSC, toggling RGB,YUV input/output */
uint32_t flags;
uint32_t csc_mv[9];
uint32_t csc_pre_bv[3];
uint32_t csc_post_bv[3];
uint32_t csc_pre_lv[6];
uint32_t csc_post_lv[6];
};
struct mdp_csc_cfg_data {
uint32_t block;
struct mdp_csc_cfg csc_data;
};
enum {
mdp_lut_igc,
mdp_lut_pgc,
mdp_lut_hist,
mdp_lut_max,
};
struct mdp_igc_lut_data {
uint32_t block;
uint32_t len, ops;
uint32_t *c0_c1_data;
uint32_t *c2_data;
};
struct mdp_ar_gc_lut_data {
uint32_t x_start;
uint32_t slope;
uint32_t offset;
};
struct mdp_pgc_lut_data {
uint32_t block;
uint32_t flags;
uint8_t num_r_stages;
uint8_t num_g_stages;
uint8_t num_b_stages;
struct mdp_ar_gc_lut_data *r_data;
struct mdp_ar_gc_lut_data *g_data;
struct mdp_ar_gc_lut_data *b_data;
};
struct mdp_hist_lut_data {
uint32_t block;
uint32_t ops;
uint32_t len;
uint32_t *data;
};
struct mdp_lut_cfg_data {
uint32_t lut_type;
union {
struct mdp_igc_lut_data igc_lut_data;
struct mdp_pgc_lut_data pgc_lut_data;
struct mdp_hist_lut_data hist_lut_data;
} data;
};
enum {
mdp_op_pcc_cfg,
mdp_op_csc_cfg,
mdp_op_lut_cfg,
mdp_op_max,
};
struct msmfb_mdp_pp {
uint32_t op;
union {
struct mdp_pcc_cfg_data pcc_cfg_data;
struct mdp_csc_cfg_data csc_cfg_data;
struct mdp_lut_cfg_data lut_cfg_data;
} data;
};
struct mdp_page_protection {
uint32_t page_protection;
};
struct mdp_mixer_info {
int pndx;
int pnum;
int ptype;
int mixer_num;
int z_order;
};
#define MAX_PIPE_PER_MIXER 4
struct msmfb_mixer_info_req {
int mixer_num;
int cnt;
struct mdp_mixer_info info[MAX_PIPE_PER_MIXER];
};
#ifdef __KERNEL__
/* get the framebuffer physical address information */
int get_fb_phys_info(unsigned long *start, unsigned long *len, int fb_num);
struct fb_info *msm_fb_get_writeback_fb(void);
int msm_fb_writeback_init(struct fb_info *info);
int msm_fb_writeback_start(struct fb_info *info);
int msm_fb_writeback_queue_buffer(struct fb_info *info,
struct msmfb_data *data);
int msm_fb_writeback_dequeue_buffer(struct fb_info *info,
struct msmfb_data *data);
int msm_fb_writeback_stop(struct fb_info *info);
int msm_fb_writeback_terminate(struct fb_info *info);
#endif
#endif /*_MSM_MDP_H_*/