From 87ce99b2514fd30298ad6e54490ca1415c998c04 Mon Sep 17 00:00:00 2001
From: David Sin <davidsin@ti.com>
Date: Thu, 17 Jan 2013 18:00:33 +0200
Subject: [PATCH] OMAP4: adding Vivante Corp 2/3D gcxxx driver files

Driver files to enable Vivante Corp 2/3D gcxxx hardware.

Change-Id: Ic7593e603a2b078879aa7a99f6dcf8074ed6b47d
Signed-off-by: Alexei Shlychkov <x0177296@ti.com>
Signed-off-by: David Sin <davidsin@ti.com>
Signed-off-by: Volodymyr Mieshkov <volodymyr.mieshkov@ti.com>
---
 drivers/misc/gcx/gcbv/Kconfig      |    6 +
 drivers/misc/gcx/gcbv/Makefile     |   12 +
 drivers/misc/gcx/gcbv/gcblit.c     |  783 +++
 drivers/misc/gcx/gcbv/gcbuffer.c   |  405 ++
 drivers/misc/gcx/gcbv/gcbv.c       | 2178 ++++++++
 drivers/misc/gcx/gcbv/gcbv.h       |  615 +++
 drivers/misc/gcx/gcbv/gcbvdebug.c  |  217 +
 drivers/misc/gcx/gcbv/gcbvdebug.h  |   26 +
 drivers/misc/gcx/gcbv/gcfill.c     |  314 ++
 drivers/misc/gcx/gcbv/gcfilter.c   | 1490 ++++++
 drivers/misc/gcx/gcbv/gcmain.c     |  264 +
 drivers/misc/gcx/gcbv/gcmain.h     |  103 +
 drivers/misc/gcx/gcbv/gcmap.c      |  364 ++
 drivers/misc/gcx/gcbv/gcparser.c   | 2416 +++++++++
 drivers/misc/gcx/gccore/Kconfig    |    5 +
 drivers/misc/gcx/gccore/Makefile   |    9 +
 drivers/misc/gcx/gccore/gcdbglog.c | 2325 ++++++++
 drivers/misc/gcx/gccore/gcdebug.c  |  555 ++
 drivers/misc/gcx/gccore/gcmain.c   | 1101 ++++
 drivers/misc/gcx/gccore/gcmain.h   |  114 +
 drivers/misc/gcx/gccore/gcmem.c    |  201 +
 drivers/misc/gcx/gccore/gcmem.h    |   36 +
 drivers/misc/gcx/gccore/gcmmu.c    | 1297 +++++
 drivers/misc/gcx/gccore/gcmmu.h    |  271 +
 drivers/misc/gcx/gccore/gcqueue.c  | 1656 ++++++
 drivers/misc/gcx/gccore/gcqueue.h  |  231 +
 drivers/misc/gcx/gcioctl/Kconfig   |    6 +
 drivers/misc/gcx/gcioctl/Makefile  |    4 +
 drivers/misc/gcx/gcioctl/gcif.c    | 1150 ++++
 drivers/misc/gcx/gcioctl/gcif.h    |   20 +
 drivers/misc/gcx/gcioctl/version.h |    4 +
 include/linux/gcbv-iface.h         |   22 +
 include/linux/gccore.h             |   37 +
 include/linux/gcdbglog.h           |  412 ++
 include/linux/gcdebug.h            |   28 +
 include/linux/gcerror.h            |  208 +
 include/linux/gcioctl.h            |  275 +
 include/linux/gcreg.h              |10335 ++++++++++++++++++++++++++++++++++++
 include/linux/gcx.h                |  106 +
 39 files changed, 29601 insertions(+), 0 deletions(-)
 create mode 100644 drivers/misc/gcx/gcbv/Kconfig
 create mode 100644 drivers/misc/gcx/gcbv/Makefile
 create mode 100644 drivers/misc/gcx/gcbv/gcblit.c
 create mode 100644 drivers/misc/gcx/gcbv/gcbuffer.c
 create mode 100644 drivers/misc/gcx/gcbv/gcbv.c
 create mode 100644 drivers/misc/gcx/gcbv/gcbv.h
 create mode 100644 drivers/misc/gcx/gcbv/gcbvdebug.c
 create mode 100644 drivers/misc/gcx/gcbv/gcbvdebug.h
 create mode 100644 drivers/misc/gcx/gcbv/gcfill.c
 create mode 100644 drivers/misc/gcx/gcbv/gcfilter.c
 create mode 100644 drivers/misc/gcx/gcbv/gcmain.c
 create mode 100644 drivers/misc/gcx/gcbv/gcmain.h
 create mode 100644 drivers/misc/gcx/gcbv/gcmap.c
 create mode 100644 drivers/misc/gcx/gcbv/gcparser.c
 create mode 100644 drivers/misc/gcx/gccore/Kconfig
 create mode 100644 drivers/misc/gcx/gccore/Makefile
 create mode 100644 drivers/misc/gcx/gccore/gcdbglog.c
 create mode 100644 drivers/misc/gcx/gccore/gcdebug.c
 create mode 100644 drivers/misc/gcx/gccore/gcmain.c
 create mode 100644 drivers/misc/gcx/gccore/gcmain.h
 create mode 100644 drivers/misc/gcx/gccore/gcmem.c
 create mode 100644 drivers/misc/gcx/gccore/gcmem.h
 create mode 100644 drivers/misc/gcx/gccore/gcmmu.c
 create mode 100644 drivers/misc/gcx/gccore/gcmmu.h
 create mode 100644 drivers/misc/gcx/gccore/gcqueue.c
 create mode 100644 drivers/misc/gcx/gccore/gcqueue.h
 create mode 100644 drivers/misc/gcx/gcioctl/Kconfig
 create mode 100644 drivers/misc/gcx/gcioctl/Makefile
 create mode 100644 drivers/misc/gcx/gcioctl/gcif.c
 create mode 100644 drivers/misc/gcx/gcioctl/gcif.h
 create mode 100644 drivers/misc/gcx/gcioctl/version.h
 create mode 100644 include/linux/gcbv-iface.h
 create mode 100644 include/linux/gccore.h
 create mode 100644 include/linux/gcdbglog.h
 create mode 100644 include/linux/gcdebug.h
 create mode 100644 include/linux/gcerror.h
 create mode 100644 include/linux/gcioctl.h
 create mode 100644 include/linux/gcreg.h
 create mode 100644 include/linux/gcx.h

diff --git a/drivers/misc/gcx/gcbv/Kconfig b/drivers/misc/gcx/gcbv/Kconfig
new file mode 100644
index 0000000..4ab8ebe
--- /dev/null
+++ b/drivers/misc/gcx/gcbv/Kconfig
@@ -0,0 +1,6 @@
+config GCBV
+	tristate "Vivante BLTsville library"
+	default y
+	depends on GCCORE
+	help
+           Vivante BLTsville library.
diff --git a/drivers/misc/gcx/gcbv/Makefile b/drivers/misc/gcx/gcbv/Makefile
new file mode 100644
index 0000000..f25080c
--- /dev/null
+++ b/drivers/misc/gcx/gcbv/Makefile
@@ -0,0 +1,12 @@
+obj-$(CONFIG_GCBV) += gcbv2d.o
+
+gcbv2d-y := \
+	gcmain.o \
+	gcbv.o \
+	gcparser.o \
+	gcmap.o \
+	gcbuffer.o \
+	gcfill.o \
+	gcblit.o \
+	gcfilter.o \
+	gcbvdebug.o
diff --git a/drivers/misc/gcx/gcbv/gcblit.c b/drivers/misc/gcx/gcbv/gcblit.c
new file mode 100644
index 0000000..54d493b
--- /dev/null
+++ b/drivers/misc/gcx/gcbv/gcblit.c
@@ -0,0 +1,783 @@
+/*
+ * This file is provided under a dual BSD/GPLv2 license.  When using or
+ * redistributing this file, you may do so under either license.
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * Copyright(c) 2012 Vivante Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * BSD LICENSE
+ *
+ * Copyright(c) 2012 Vivante Corporation. 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 Vivante Corporation 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 AND FITNESS FOR A PARTICULAR PURPOSE
+ * 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.
+ */
+
+#include "gcbv.h"
+
+#define GCZONE_NONE		0
+#define GCZONE_ALL		(~0U)
+#define GCZONE_BLEND		(1 << 0)
+#define GCZONE_SURF		(1 << 1)
+#define GCZONE_BLIT		(1 << 2)
+
+GCDBG_FILTERDEF(blit, GCZONE_NONE,
+		"blend",
+		"surf",
+		"blit")
+
+
+static enum bverror do_blit_end(struct bvbltparams *bvbltparams,
+				struct gcbatch *batch)
+{
+	enum bverror bverror;
+	struct gcblit *gcblit;
+	struct gcmobltconfig *gcmobltconfig;
+	struct gcmostartde *gcmostartde;
+
+	GCENTER(GCZONE_BLIT);
+
+	/* Get a shortcut to the operation specific data. */
+	gcblit = &batch->op.blit;
+
+	GCDBG(GCZONE_BLIT, "finalizing the blit, scrcount = %d\n",
+	      gcblit->srccount);
+
+	/***********************************************************************
+	 * Configure the operation.
+	 */
+
+	/* Allocate command buffer. */
+	bverror = claim_buffer(bvbltparams, batch,
+			       sizeof(struct gcmobltconfig),
+			       (void **) &gcmobltconfig);
+	if (bverror != BVERR_NONE)
+		goto exit;
+
+	/* Configure multi-source control. */
+	gcmobltconfig->multisource_ldst = gcmobltconfig_multisource_ldst;
+	gcmobltconfig->multisource.raw = 0;
+	gcmobltconfig->multisource.reg.srccount = gcblit->srccount - 1;
+
+	GCDBG(GCZONE_BLIT, "blockenable = %d\n", gcblit->blockenable);
+	if (gcblit->blockenable) {
+		gcmobltconfig->multisource.reg.horblock
+			= GCREG_DE_MULTI_SOURCE_HORIZONTAL_BLOCK_PIXEL16;
+		gcmobltconfig->multisource.reg.verblock
+			= GCREG_DE_MULTI_SOURCE_VERTICAL_BLOCK_LINE64;
+	} else {
+		gcmobltconfig->multisource.reg.horblock
+			= GCREG_DE_MULTI_SOURCE_HORIZONTAL_BLOCK_PIXEL128;
+		gcmobltconfig->multisource.reg.verblock
+			= GCREG_DE_MULTI_SOURCE_VERTICAL_BLOCK_LINE1;
+	}
+
+	/* Set destination configuration. */
+	GCDBG(GCZONE_BLIT, "  swizzle code = %d\n", gcblit->swizzle);
+	GCDBG(GCZONE_BLIT, "  format code = %d\n", gcblit->format);
+
+	gcmobltconfig->dstconfig_ldst = gcmobltconfig_dstconfig_ldst;
+	gcmobltconfig->dstconfig.raw = 0;
+	gcmobltconfig->dstconfig.reg.swizzle = gcblit->swizzle;
+	gcmobltconfig->dstconfig.reg.format = gcblit->format;
+	gcmobltconfig->dstconfig.reg.endian = gcblit->endian;
+	gcmobltconfig->dstconfig.reg.command = gcblit->multisrc
+		? GCREG_DEST_CONFIG_COMMAND_MULTI_SOURCE_BLT
+		: GCREG_DEST_CONFIG_COMMAND_BIT_BLT;
+
+	/***********************************************************************
+	 * Start the operation.
+	 */
+
+	/* Allocate command buffer. */
+	bverror = claim_buffer(bvbltparams, batch,
+			       sizeof(struct gcmostartde),
+			       (void **) &gcmostartde);
+	if (bverror != BVERR_NONE)
+		goto exit;
+
+	/* Set START_DE command. */
+	gcmostartde->startde.cmd.fld = gcfldstartde;
+
+	/* Set destination rectangle. */
+	gcmostartde->rect.left = gcblit->dstrect.left;
+	gcmostartde->rect.top = gcblit->dstrect.top;
+	gcmostartde->rect.right = gcblit->dstrect.right;
+	gcmostartde->rect.bottom = gcblit->dstrect.bottom;
+
+	GCDBG(GCZONE_BLIT, "dstrect = (%d,%d)-(%d,%d)\n",
+	      gcmostartde->rect.left, gcmostartde->rect.top,
+	      gcmostartde->rect.right, gcmostartde->rect.bottom);
+
+	/* Reset the finalizer. */
+	batch->batchend = do_end;
+
+	gcbv_debug_blt(gcblit->srccount,
+		       abs(gcblit->dstrect.right - gcblit->dstrect.left),
+		       abs(gcblit->dstrect.bottom - gcblit->dstrect.top));
+
+exit:
+	GCEXITARG(GCZONE_BLIT, "bv%s = %d\n",
+		  (bverror == BVERR_NONE) ? "result" : "error", bverror);
+	return bverror;
+}
+
+enum bverror do_blit(struct bvbltparams *bvbltparams,
+		     struct gcbatch *batch,
+		     struct gcsurface *srcinfo)
+{
+	enum bverror bverror = BVERR_NONE;
+	struct gccontext *gccontext = get_context();
+
+	struct gcmosrc0 *gcmosrc0;
+	struct gcmosrc *gcmosrc;
+	struct gcblit *gcblit;
+
+	unsigned int index;
+	struct bvbuffmap *dstmap = NULL;
+	struct bvbuffmap *srcmap = NULL;
+
+	struct gcsurface *dstinfo;
+	int dstshiftX, dstshiftY;
+	int dstpixalign, dstbyteshift;
+	int dstoffsetX, dstoffsetY;
+
+	int adjust, srcshiftX, srcshiftY;
+	unsigned int physwidth, physheight;
+	bool orthogonal;
+	bool multisrc;
+	unsigned int batchfinalize;
+
+	int srcleftedge, srctopedge;
+	int dstleftedge, dsttopedge;
+
+	struct gcrect *srcorig, *srcclip, *srcadj;
+	struct gcrect *dstorig, *dstclip, *dstadj;
+
+	GCENTER(GCZONE_BLIT);
+
+	/* 3-plane source not supported. */
+	if ((srcinfo->format.type == BVFMT_YUV) &&
+	    (srcinfo->format.cs.yuv.planecount == 3)) {
+		BVSETBLTERROR((srcinfo->index == 0)
+					? BVERR_SRC1GEOM_FORMAT
+					: BVERR_SRC2GEOM_FORMAT,
+			      "unsupported source%d format.",
+			      srcinfo->index + 1);
+		goto exit;
+	}
+
+	/* Zero-fill for source is not supported. */
+	if (srcinfo->format.zerofill) {
+		BVSETBLTERROR((srcinfo->index == 0)
+					? BVERR_SRC1GEOM_FORMAT
+					: BVERR_SRC2GEOM_FORMAT,
+			      "0 filling is not supported.");
+		goto exit;
+	}
+
+	/***********************************************************************
+	 * Parse destination.
+	 */
+
+	/* Get a shortcut to the destination surface. */
+	dstinfo = &batch->dstinfo;
+
+	/* Get destination rectangle shortcuts. */
+	dstorig = &dstinfo->rect.orig;
+	dstclip = &dstinfo->rect.clip;
+	dstadj = &dstinfo->rect.adj;
+
+	/* Parse destination parameters. */
+	bverror = parse_destination(bvbltparams, batch);
+	if (bverror != BVERR_NONE)
+		goto exit;
+
+	/* Ignore the blit if destination rectangle is empty. */
+	if (null_rect(dstclip)) {
+		GCDBG(GCZONE_SURF, "empty destination rectangle.\n");
+		goto exit;
+	}
+
+	/* Adjust surface angles if necessary. */
+	adjust_angle(srcinfo, dstinfo);
+
+
+	/***********************************************************************
+	 * Determine source surface alignment offset.
+	 */
+
+	/* Assume multi-source is possible. */
+	multisrc = true;
+
+	/* Assume no additional shift is necessary. */
+	srcshiftX = 0;
+	srcshiftY = 0;
+
+	/* Get source rectangle shortcuts. */
+	srcorig = &srcinfo->rect.orig;
+	srcclip = &srcinfo->rect.clip;
+	srcadj = &srcinfo->rect.adj;
+
+	/* Determine whether the source and the destination are orthogonal
+	 * to each other. */
+	orthogonal = (srcinfo->angle % 2) != (dstinfo->angle % 2);
+
+	/* Compute clipped source rectangle. */
+	srcclip->left   = srcorig->left   + batch->clipdelta.left;
+	srcclip->top    = srcorig->top    + batch->clipdelta.top;
+	srcclip->right  = srcorig->right  + batch->clipdelta.right;
+	srcclip->bottom = srcorig->bottom + batch->clipdelta.bottom;
+	GCPRINT_RECT(GCZONE_SURF, "clipped source", srcclip);
+
+	/* Validate the source rectangle. */
+	if (!valid_rect(srcinfo, srcclip)) {
+		BVSETBLTERROR((srcinfo->index == 0)
+					? BVERR_SRC1RECT
+					: BVERR_SRC2RECT,
+			      "invalid source rectangle.");
+		goto exit;
+	}
+
+	/* Ignore the blit if source rectangle is empty. */
+	if (null_rect(srcclip)) {
+		GCDBG(GCZONE_SURF, "empty source rectangle.\n");
+		goto exit;
+	}
+
+	/* Determine source and destination physical origin. */
+	switch (srcinfo->angle) {
+	case ROT_ANGLE_0:
+		srcleftedge = srcclip->left;
+		srctopedge  = srcclip->top;
+		dstleftedge = dstadj->left;
+		dsttopedge  = dstadj->top;
+		break;
+
+	case ROT_ANGLE_90:
+		srcleftedge = srcclip->top;
+		srctopedge  = srcinfo->width - srcclip->left;
+		dstleftedge = dstadj->top;
+		dsttopedge  = dstinfo->adjwidth - dstadj->left;
+		break;
+
+	case ROT_ANGLE_180:
+		srcleftedge = srcinfo->width - srcclip->left;
+		srctopedge  = srcinfo->height - srcclip->top;
+		dstleftedge = dstinfo->adjwidth - dstadj->left;
+		dsttopedge  = dstinfo->adjheight - dstadj->top;
+		break;
+
+	case ROT_ANGLE_270:
+		srcleftedge = srcinfo->height - srcclip->top;
+		srctopedge  = srcclip->left;
+		dstleftedge = dstinfo->adjheight - dstadj->top;
+		dsttopedge  = dstadj->left;
+		break;
+
+	default:
+		srcleftedge = 0;
+		srctopedge  = 0;
+		dstleftedge = 0;
+		dsttopedge  = 0;
+	}
+
+	/* Compute the source surface shift. */
+	srcinfo->xpixalign = srcleftedge - dstleftedge;
+	srcinfo->ypixalign = srctopedge  - dsttopedge;
+
+	/* Compute the source surface offset in bytes. */
+	srcinfo->bytealign1
+		= srcinfo->ypixalign * (int) srcinfo->stride1
+		+ srcinfo->xpixalign * (int) srcinfo->format.bitspp / 8;
+
+	GCDBG(GCZONE_SURF, "source surface %d:\n", srcinfo->index + 1);
+	GCDBG(GCZONE_SURF, "  surface offset (pixels) = %d,%d\n",
+	      srcinfo->xpixalign, srcinfo->ypixalign);
+	GCDBG(GCZONE_SURF, "  surface offset (bytes) = 0x%08X\n",
+	      srcinfo->bytealign1);
+
+	/* Compute the source offset in pixels needed to compensate
+	 * for the surface base address misalignment if any. */
+	adjust = get_pixel_offset(srcinfo, srcinfo->bytealign1);
+
+	/* Account for the newly created misalignment if any. */
+	srcinfo->bytealign1 += adjust * (int) srcinfo->format.bitspp / 8;
+	srcinfo->xpixalign += adjust;
+	srcshiftX += adjust;
+
+	GCDBG(GCZONE_SURF, "  horizontal alignment adjustment (pixels) = %d\n",
+	      adjust);
+	GCDBG(GCZONE_SURF, "  adjusted surface offset (pixels) = %d,%d\n",
+	      srcinfo->xpixalign, srcinfo->ypixalign);
+	GCDBG(GCZONE_SURF, "  additional surface offset (pixels) = %d,%d\n",
+	      srcshiftX, srcshiftY);
+	GCDBG(GCZONE_SURF, "  adjusted surface offset (bytes) = 0x%08X\n",
+	      srcinfo->bytealign1);
+
+	/* Compute U/V plane offsets. */
+	if ((srcinfo->format.type == BVFMT_YUV) &&
+	    (srcinfo->format.cs.yuv.planecount > 1))
+		set_computeyuv(srcinfo, srcinfo->xpixalign, srcinfo->ypixalign);
+
+	/* Set precomputed destination adjustments based on the destination
+	 * base address misalignment only. */
+	dstshiftX = dstinfo->xpixalign;
+	dstshiftY = dstinfo->ypixalign;
+
+	/* Apply source adjustemnts. */
+	if (srcinfo->angle == dstinfo->angle) {
+		dstshiftX += srcshiftX;
+		dstshiftY += srcshiftY;
+	} else if (((srcinfo->angle + 3) % 4) == dstinfo->angle) {
+		dstshiftY += srcshiftX;
+	} else if (((srcinfo->angle + 1) % 4) == dstinfo->angle) {
+		dstshiftX += srcshiftY;
+	}
+
+	/* Compute the destination surface offset in bytes. */
+	dstbyteshift = dstshiftY * (int) dstinfo->stride1
+		     + dstshiftX * (int) dstinfo->format.bitspp / 8;
+
+	/* Compute the destination offset in pixels needed to compensate
+	 * for the surface base address misalignment if any. If dstpixalign
+	 * comes out anything other than zero, multisource blit cannot be
+	 * performed. */
+	dstpixalign = get_pixel_offset(dstinfo, dstbyteshift);
+	if (dstpixalign != 0) {
+		GCDBG(GCZONE_SURF,
+		      "  disabling multi-source, "
+		      "destination needs to be realigned again.\n");
+		multisrc = false;
+	}
+
+	GCDBG(GCZONE_SURF, "destination surface:\n");
+	GCDBG(GCZONE_SURF, "  surface offset (pixels) = %d,%d\n",
+	      dstshiftX, dstshiftY);
+	GCDBG(GCZONE_SURF, "  surface offset (bytes) = 0x%08X\n",
+	      dstbyteshift);
+	GCDBG(GCZONE_SURF, "  realignment = %d\n",
+	      dstpixalign);
+
+	if (multisrc) {
+		GCDBG(GCZONE_SURF, "multi-source enabled.\n");
+
+		/* Source origin is not used in multi-source setup. */
+		srcadj->left = 0;
+		srcadj->top = 0;
+
+		/* Set new surface shift. */
+		if (dstinfo->bytealign1 != dstbyteshift) {
+			GCDBG(GCZONE_SURF,
+			      "destination alignment changed.\n");
+			dstinfo->bytealign1 = dstbyteshift;
+			dstinfo->surfdirty = true;
+		}
+
+		/* Adjust the destination to match the source geometry. */
+		switch (srcinfo->angle) {
+		case ROT_ANGLE_0:
+			/* Adjust the destination horizontally. */
+			dstoffsetX = srcshiftX;
+			dstoffsetY = srcshiftY;
+
+			/* Apply the source alignment. */
+			if ((dstinfo->angle % 2) == 0) {
+				physwidth  = dstinfo->physwidth  - srcshiftX;
+				physheight = dstinfo->physheight - srcshiftY;
+			} else {
+				physwidth  = dstinfo->physwidth  - srcshiftY;
+				physheight = dstinfo->physheight - srcshiftX;
+			}
+			break;
+
+		case ROT_ANGLE_90:
+			/* Adjust the destination vertically. */
+			dstoffsetX = srcshiftY;
+			dstoffsetY = srcshiftX;
+
+			/* Apply the source alignment. */
+			if ((dstinfo->angle % 2) == 0) {
+				physwidth  = dstinfo->physwidth  - srcshiftY;
+				physheight = dstinfo->physheight - srcshiftX;
+			} else {
+				physwidth  = dstinfo->physwidth  - srcshiftX;
+				physheight = dstinfo->physheight - srcshiftY;
+			}
+			break;
+
+		case ROT_ANGLE_180:
+			/* No adjustment necessary. */
+			dstoffsetX = 0;
+			dstoffsetY = 0;
+
+			/* Apply the source alignment. */
+			if ((dstinfo->angle % 2) == 0) {
+				physwidth  = dstinfo->physwidth  - srcshiftX;
+				physheight = dstinfo->physheight - srcshiftY;
+			} else {
+				physwidth  = dstinfo->physwidth  - srcshiftY;
+				physheight = dstinfo->physheight - srcshiftX;
+			}
+			break;
+
+		case ROT_ANGLE_270:
+			/* No adjustment necessary. */
+			dstoffsetX = 0;
+			dstoffsetY = 0;
+
+			/* Apply the source alignment. */
+			if ((dstinfo->angle % 2) == 0) {
+				physwidth  = dstinfo->physwidth  - srcshiftY;
+				physheight = dstinfo->physheight - srcshiftX;
+			} else {
+				physwidth  = dstinfo->physwidth  - srcshiftX;
+				physheight = dstinfo->physheight - srcshiftY;
+			}
+			break;
+
+		default:
+			physwidth = 0;
+			physheight = 0;
+			dstoffsetX = 0;
+			dstoffsetY = 0;
+		}
+
+		/* Source geometry is now the same as the destination. */
+		if (orthogonal) {
+			srcinfo->physwidth  = physheight;
+			srcinfo->physheight = physwidth;
+		} else {
+			srcinfo->physwidth  = physwidth;
+			srcinfo->physheight = physheight;
+		}
+
+		/* Set new surface size. */
+		if ((physwidth  != dstinfo->physwidth) ||
+		    (physheight != dstinfo->physheight)) {
+			dstinfo->physwidth  = physwidth;
+			dstinfo->physheight = physheight;
+			dstinfo->surfdirty = true;
+		}
+
+		/* Set new offset. */
+		if ((batch->dstoffsetX != dstoffsetX) ||
+		    (batch->dstoffsetY != dstoffsetY)) {
+			batch->dstoffsetX = dstoffsetX;
+			batch->dstoffsetY = dstoffsetY;
+			dstinfo->surfdirty = true;
+		}
+	} else {
+		GCDBG(GCZONE_SURF, "multi-source disabled.\n");
+
+		/* Determine surface size and render rectangle. */
+		process_rotation(srcinfo);
+
+		/* No adjustment necessary for single-source. */
+		dstoffsetX = 0;
+		dstoffsetY = 0;
+	}
+
+	batchfinalize = 0;
+
+	/* Reached maximum number of sources? */
+	if (batch->op.blit.srccount == gccontext->gccaps.maxsource)
+		batchfinalize |= GCBV_BATCH_FINALIZE_SRCCOUNT;
+
+	/* Previous operation was not blit? */
+	if (batch->batchend != do_blit_end)
+		batchfinalize |= GCBV_BATCH_FINALIZE_OPERATION;
+
+	/* Previous blit was not multi-sourced? */
+	else if (!batch->op.blit.multisrc)
+		batchfinalize |= GCBV_BATCH_FINALIZE_MULTISRC;
+
+	/* Current blit is not multi-sourced? */
+	if (!multisrc)
+		batchfinalize |= GCBV_BATCH_FINALIZE_ALIGN;
+
+	/* Destination has changed? */
+	if (dstinfo->surfdirty)
+		batchfinalize |= GCBV_BATCH_FINALIZE_FLAGS_DST;
+
+	if (dstinfo->cliprectdirty)
+		batchfinalize |= GCBV_BATCH_FINALIZE_FLAGS_CLIPRECT;
+
+	if (dstinfo->destrectdirty)
+		batchfinalize |= GCBV_BATCH_FINALIZE_FLAGS_DESTRECT;
+
+	/* Check if we need to finalize existing batch. */
+	if (batchfinalize) {
+		if (batch->batchend == do_blit_end)
+			gcbv_debug_finalize_batch(batchfinalize);
+
+		/* Finalize existing batch if any. */
+		bverror = batch->batchend(bvbltparams, batch);
+		if (bverror != BVERR_NONE)
+			goto exit;
+
+		/* Blit batch. */
+		batch->batchend = do_blit_end;
+
+		/* Initialize the new batch. */
+		gcblit = &batch->op.blit;
+		gcblit->blockenable = false;
+		gcblit->srccount = 0;
+		gcblit->multisrc = multisrc;
+
+		/* Set the destination format. */
+		gcblit->format  = dstinfo->format.format;
+		gcblit->swizzle = dstinfo->format.swizzle;
+		gcblit->endian = dstinfo->format.endian;
+
+		/* Set the destination coordinates. */
+		gcblit->dstrect.left   = dstadj->left   - dstoffsetX;
+		gcblit->dstrect.top    = dstadj->top    - dstoffsetY;
+		gcblit->dstrect.right  = dstadj->right  - dstoffsetX;
+		gcblit->dstrect.bottom = dstadj->bottom - dstoffsetY;
+	}
+
+	if (dstinfo->surfdirty) {
+		/* Map the destination. */
+		bverror = do_map(dstinfo->buf.desc, batch, &dstmap);
+		if (bverror != BVERR_NONE) {
+			bvbltparams->errdesc = gccontext->bverrorstr;
+			goto exit;
+		}
+
+		/* Set the new destination. */
+		bverror = set_dst(bvbltparams, batch, dstmap);
+		if (bverror != BVERR_NONE)
+			goto exit;
+	}
+
+	/* Map the source. */
+	bverror = do_map(srcinfo->buf.desc, batch, &srcmap);
+	if (bverror != BVERR_NONE) {
+		bvbltparams->errdesc = gccontext->bverrorstr;
+		goto exit;
+	}
+
+	/***********************************************************************
+	** Configure source.
+	*/
+
+	/* We need to walk in blocks if the source and the destination
+	 * surfaces are orthogonal to each other. */
+	if (orthogonal)
+		batch->op.blit.blockenable = true;
+
+	/* Shortcut to the register index. */
+	index = batch->op.blit.srccount;
+
+	/* Set surface parameters. */
+	if (index == 0) {
+		/* Allocate command buffer. */
+		bverror = claim_buffer(bvbltparams, batch,
+				       sizeof(struct gcmosrc0),
+				       (void **) &gcmosrc0);
+		if (bverror != BVERR_NONE)
+			goto exit;
+
+		add_fixup(bvbltparams, batch, &gcmosrc0->address,
+			  srcinfo->bytealign1);
+
+		gcmosrc0->config_ldst = gcmosrc0_config_ldst;
+		gcmosrc0->address = GET_MAP_HANDLE(srcmap);
+		gcmosrc0->stride = srcinfo->stride1;
+		gcmosrc0->rotation.raw = 0;
+		gcmosrc0->rotation.reg.surf_width = srcinfo->physwidth;
+		gcmosrc0->config.raw = 0;
+		gcmosrc0->config.reg.swizzle = srcinfo->format.swizzle;
+		gcmosrc0->config.reg.format = srcinfo->format.format;
+		gcmosrc0->config.reg.endian = srcinfo->format.endian;
+		gcmosrc0->origin.reg.x = srcadj->left;
+		gcmosrc0->origin.reg.y = srcadj->top;
+		gcmosrc0->size.reg = gcregsrcsize_max;
+
+		gcmosrc0->rotation_ldst = gcmosrc0_rotation_ldst;
+		gcmosrc0->rotationheight.reg.height = srcinfo->physheight;
+		gcmosrc0->rotationangle.raw = 0;
+		gcmosrc0->rotationangle.reg.src = rotencoding[srcinfo->angle];
+		gcmosrc0->rotationangle.reg.dst = rotencoding[dstinfo->angle];
+		gcmosrc0->rotationangle.reg.src_mirror = srcinfo->mirror;
+		gcmosrc0->rotationangle.reg.dst_mirror = GCREG_MIRROR_NONE;
+
+		gcmosrc0->rop_ldst = gcmosrc0_rop_ldst;
+		gcmosrc0->rop.raw = 0;
+		gcmosrc0->rop.reg.type = GCREG_ROP_TYPE_ROP3;
+		gcmosrc0->rop.reg.fg = (unsigned char) srcinfo->rop;
+
+		gcmosrc0->mult_ldst = gcmosrc0_mult_ldst;
+		gcmosrc0->mult.raw = 0;
+		gcmosrc0->mult.reg.srcglobalpremul = srcinfo->srcglobalpremul;
+
+		if (srcinfo->format.premultiplied)
+			gcmosrc0->mult.reg.srcpremul
+			= GCREG_COLOR_MULTIPLY_MODES_SRC_PREMULTIPLY_DISABLE;
+		else
+			gcmosrc0->mult.reg.srcpremul
+			= GCREG_COLOR_MULTIPLY_MODES_SRC_PREMULTIPLY_ENABLE;
+
+		if (dstinfo->format.premultiplied) {
+			gcmosrc0->mult.reg.dstpremul
+			= GCREG_COLOR_MULTIPLY_MODES_SRC_PREMULTIPLY_DISABLE;
+
+			gcmosrc0->mult.reg.dstdemul
+			= GCREG_COLOR_MULTIPLY_MODES_DST_DEMULTIPLY_DISABLE;
+		} else {
+			gcmosrc0->mult.reg.dstpremul
+			= GCREG_COLOR_MULTIPLY_MODES_SRC_PREMULTIPLY_ENABLE;
+
+			gcmosrc0->mult.reg.dstdemul
+			= GCREG_COLOR_MULTIPLY_MODES_DST_DEMULTIPLY_ENABLE;
+		}
+
+		/* Program blending. */
+		bverror = set_blending(bvbltparams, batch, srcinfo);
+		if (bverror != BVERR_NONE)
+			goto exit;
+
+		/* Program YUV source. */
+		if (srcinfo->format.type == BVFMT_YUV) {
+			bverror = set_yuvsrc(bvbltparams, batch,
+					     srcinfo, srcmap);
+			if (bverror != BVERR_NONE)
+				goto exit;
+		}
+	} else {
+		/* Allocate command buffer. */
+		bverror = claim_buffer(bvbltparams, batch,
+				       sizeof(struct gcmosrc),
+				       (void **) &gcmosrc);
+		if (bverror != BVERR_NONE)
+			goto exit;
+
+		add_fixup(bvbltparams, batch, &gcmosrc->address,
+			  srcinfo->bytealign1);
+
+		gcmosrc->address_ldst = gcmosrc_address_ldst[index];
+		gcmosrc->address = GET_MAP_HANDLE(srcmap);
+		gcmosrc->stride_ldst = gcmosrc_stride_ldst[index];
+		gcmosrc->stride = srcinfo->stride1;
+
+		gcmosrc->rotation_ldst = gcmosrc_rotation_ldst[index];
+		gcmosrc->rotation.raw = 0;
+		gcmosrc->rotation.reg.surf_width = srcinfo->physwidth;
+
+		gcmosrc->config_ldst = gcmosrc_config_ldst[index];
+		gcmosrc->config.raw = 0;
+		gcmosrc->config.reg.swizzle = srcinfo->format.swizzle;
+		gcmosrc->config.reg.format = srcinfo->format.format;
+		gcmosrc->config.reg.endian = srcinfo->format.endian;
+
+		gcmosrc->origin_ldst = gcmosrc_origin_ldst[index];
+		gcmosrc->origin.reg.x = srcadj->left;
+		gcmosrc->origin.reg.y = srcadj->top;
+
+		gcmosrc->size_ldst = gcmosrc_size_ldst[index];
+		gcmosrc->size.reg = gcregsrcsize_max;
+
+		gcmosrc->rotationheight_ldst
+			= gcmosrc_rotationheight_ldst[index];
+		gcmosrc->rotationheight.reg.height = srcinfo->physheight;
+
+		gcmosrc->rotationangle_ldst
+			= gcmosrc_rotationangle_ldst[index];
+		gcmosrc->rotationangle.raw = 0;
+		gcmosrc->rotationangle.reg.src = rotencoding[srcinfo->angle];
+		gcmosrc->rotationangle.reg.dst = rotencoding[dstinfo->angle];
+		gcmosrc->rotationangle.reg.src_mirror = srcinfo->mirror;
+		gcmosrc->rotationangle.reg.dst_mirror = GCREG_MIRROR_NONE;
+
+		gcmosrc->rop_ldst = gcmosrc_rop_ldst[index];
+		gcmosrc->rop.raw = 0;
+		gcmosrc->rop.reg.type = GCREG_ROP_TYPE_ROP3;
+		gcmosrc->rop.reg.fg = (unsigned char) srcinfo->rop;
+
+		gcmosrc->mult_ldst = gcmosrc_mult_ldst[index];
+		gcmosrc->mult.raw = 0;
+		gcmosrc->mult.reg.srcglobalpremul = srcinfo->srcglobalpremul;
+
+		if (srcinfo->format.premultiplied)
+			gcmosrc->mult.reg.srcpremul
+			= GCREG_COLOR_MULTIPLY_MODES_SRC_PREMULTIPLY_DISABLE;
+		else
+			gcmosrc->mult.reg.srcpremul
+			= GCREG_COLOR_MULTIPLY_MODES_SRC_PREMULTIPLY_ENABLE;
+
+		if (dstinfo->format.premultiplied) {
+			gcmosrc->mult.reg.dstpremul
+			= GCREG_COLOR_MULTIPLY_MODES_SRC_PREMULTIPLY_DISABLE;
+
+			gcmosrc->mult.reg.dstdemul
+			= GCREG_COLOR_MULTIPLY_MODES_DST_DEMULTIPLY_DISABLE;
+		} else {
+			gcmosrc->mult.reg.dstpremul
+			= GCREG_COLOR_MULTIPLY_MODES_SRC_PREMULTIPLY_ENABLE;
+
+			gcmosrc->mult.reg.dstdemul
+			= GCREG_COLOR_MULTIPLY_MODES_DST_DEMULTIPLY_ENABLE;
+		}
+
+		/* Program blending. */
+		bverror = set_blending_index(bvbltparams, batch,
+					     srcinfo, index);
+		if (bverror != BVERR_NONE)
+			goto exit;
+
+		/* Program YUV source. */
+		if (srcinfo->format.type == BVFMT_YUV) {
+			bverror = set_yuvsrc_index(bvbltparams, batch,
+						   srcinfo, srcmap, index);
+			if (bverror != BVERR_NONE)
+				goto exit;
+		}
+	}
+
+	batch->op.blit.srccount += 1;
+
+exit:
+	GCEXITARG(GCZONE_BLIT, "bv%s = %d\n",
+		  (bverror == BVERR_NONE) ? "result" : "error", bverror);
+	return bverror;
+}
diff --git a/drivers/misc/gcx/gcbv/gcbuffer.c b/drivers/misc/gcx/gcbv/gcbuffer.c
new file mode 100644
index 0000000..1d1fde7
--- /dev/null
+++ b/drivers/misc/gcx/gcbv/gcbuffer.c
@@ -0,0 +1,405 @@
+/*
+ * This file is provided under a dual BSD/GPLv2 license.  When using or
+ * redistributing this file, you may do so under either license.
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * Copyright(c) 2012 Vivante Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * BSD LICENSE
+ *
+ * Copyright(c) 2012 Vivante Corporation. 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 Vivante Corporation 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 AND FITNESS FOR A PARTICULAR PURPOSE
+ * 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.
+ */
+
+#include "gcbv.h"
+
+#define GCZONE_NONE		0
+#define GCZONE_ALL		(~0U)
+#define GCZONE_BATCH_ALLOC	(1 << 0)
+#define GCZONE_BUFFER_ALLOC	(1 << 1)
+#define GCZONE_FIXUP_ALLOC	(1 << 2)
+#define GCZONE_FIXUP		(1 << 3)
+
+GCDBG_FILTERDEF(buffer, GCZONE_NONE,
+		"batchalloc",
+		"bufferalloc"
+		"fixupalloc",
+		"fixup")
+
+
+/*******************************************************************************
+** Miscellaneous defines and macros.
+*/
+
+#define GC_BUFFER_INIT_SIZE \
+( \
+	GC_BUFFER_SIZE - max(sizeof(struct gcbuffer), GC_BUFFER_RESERVE) \
+)
+
+#define GC_BUFFER_RESERVE \
+( \
+	sizeof(struct gcmopipesel) + \
+	sizeof(struct gcmommumaster) + \
+	sizeof(struct gcmommuflush) + \
+	sizeof(struct gcmosignal) + \
+	sizeof(struct gccmdend) \
+)
+
+
+/*******************************************************************************
+ * Batch/command buffer management.
+ */
+
+enum bverror do_end(struct bvbltparams *bvbltparams,
+		    struct gcbatch *gcbatch)
+{
+	return BVERR_NONE;
+}
+
+enum bverror allocate_batch(struct bvbltparams *bvbltparams,
+			    struct gcbatch **gcbatch)
+{
+	enum bverror bverror;
+	struct gccontext *gccontext = get_context();
+	struct gcbatch *temp;
+	struct gcbuffer *gcbuffer;
+
+	GCENTER(GCZONE_BATCH_ALLOC);
+
+	/* Lock access to batch management. */
+	GCLOCK(&gccontext->batchlock);
+
+	if (list_empty(&gccontext->batchvac)) {
+		temp = gcalloc(struct gcbatch, sizeof(struct gcbatch));
+		if (temp == NULL) {
+			BVSETBLTERROR(BVERR_OOM,
+				      "batch header allocation failed");
+			goto exit;
+		}
+
+		GCDBG(GCZONE_BATCH_ALLOC, "allocated new batch = 0x%08X\n",
+		      (unsigned int) temp);
+	} else {
+		struct list_head *head;
+		head = gccontext->batchvac.next;
+		temp = list_entry(head, struct gcbatch, link);
+		list_del(head);
+
+		GCDBG(GCZONE_BATCH_ALLOC, "reusing batch = 0x%08X\n",
+		      (unsigned int) temp);
+	}
+
+	memset(temp, 0, sizeof(struct gcbatch));
+	temp->structsize = sizeof(struct gcbatch);
+	temp->batchend = do_end;
+	INIT_LIST_HEAD(&temp->buffer);
+	INIT_LIST_HEAD(&temp->unmap);
+	INIT_LIST_HEAD(&temp->link);
+
+	bverror = append_buffer(bvbltparams, temp, &gcbuffer);
+	if (bverror != BVERR_NONE) {
+		free_batch(temp);
+		goto exit;
+	}
+
+	*gcbatch = temp;
+
+	GCDBG(GCZONE_BATCH_ALLOC, "batch allocated = 0x%08X\n",
+	      (unsigned int) temp);
+
+exit:
+	/* Unlock access to batch management. */
+	GCUNLOCK(&gccontext->batchlock);
+
+	GCEXITARG(GCZONE_BATCH_ALLOC, "bv%s = %d\n",
+		  (bverror == BVERR_NONE) ? "result" : "error", bverror);
+	return bverror;
+}
+
+void free_batch(struct gcbatch *gcbatch)
+{
+	struct list_head *head;
+	struct gccontext *gccontext = get_context();
+	struct gcbuffer *gcbuffer;
+
+	GCENTERARG(GCZONE_BATCH_ALLOC, "batch = 0x%08X\n",
+		   (unsigned int) gcbatch);
+
+	/* Lock access. */
+	GCLOCK(&gccontext->batchlock);
+	GCLOCK(&gccontext->bufferlock);
+	GCLOCK(&gccontext->fixuplock);
+	GCLOCK(&gccontext->maplock);
+
+	/* Free implicit unmappings. */
+	list_splice_init(&gcbatch->unmap, &gccontext->unmapvac);
+
+	/* Free command buffers. */
+	while (!list_empty(&gcbatch->buffer)) {
+		head = gcbatch->buffer.next;
+		gcbuffer = list_entry(head, struct gcbuffer, link);
+
+		/* Free fixups. */
+		list_splice_init(&gcbuffer->fixup, &gccontext->fixupvac);
+
+		/* Free the command buffer. */
+		list_move(&gcbuffer->link, &gccontext->buffervac);
+	}
+
+	/* Free the batch. */
+	list_add(&gcbatch->link, &gccontext->batchvac);
+
+	/* Unlock access. */
+	GCUNLOCK(&gccontext->maplock);
+	GCUNLOCK(&gccontext->fixuplock);
+	GCUNLOCK(&gccontext->bufferlock);
+	GCUNLOCK(&gccontext->batchlock);
+
+	GCEXIT(GCZONE_BATCH_ALLOC);
+}
+
+enum bverror append_buffer(struct bvbltparams *bvbltparams,
+			   struct gcbatch *gcbatch,
+			   struct gcbuffer **gcbuffer)
+{
+	enum bverror bverror;
+	struct gccontext *gccontext = get_context();
+	struct gcbuffer *temp;
+
+	GCENTERARG(GCZONE_BUFFER_ALLOC, "batch = 0x%08X\n",
+		   (unsigned int) gcbatch);
+
+	/* Lock access to buffer management. */
+	GCLOCK(&gccontext->bufferlock);
+
+	if (list_empty(&gccontext->buffervac)) {
+		temp = gcalloc(struct gcbuffer, GC_BUFFER_SIZE);
+		if (temp == NULL) {
+			BVSETBLTERROR(BVERR_OOM,
+				      "command buffer allocation failed");
+			goto exit;
+		}
+
+		list_add_tail(&temp->link, &gcbatch->buffer);
+
+		GCDBG(GCZONE_BUFFER_ALLOC, "allocated new buffer = 0x%08X\n",
+		      (unsigned int) temp);
+	} else {
+		struct list_head *head;
+		head = gccontext->buffervac.next;
+		temp = list_entry(head, struct gcbuffer, link);
+
+		list_move_tail(&temp->link, &gcbatch->buffer);
+
+		GCDBG(GCZONE_BUFFER_ALLOC, "reusing buffer = 0x%08X\n",
+		      (unsigned int) temp);
+	}
+
+	INIT_LIST_HEAD(&temp->fixup);
+	temp->pixelcount = 0;
+	temp->head = temp->tail = (unsigned int *) (temp + 1);
+	temp->available = GC_BUFFER_INIT_SIZE;
+
+	GCDBG(GCZONE_BUFFER_ALLOC, "new buffer appended = 0x%08X\n",
+	      (unsigned int) temp);
+
+	*gcbuffer = temp;
+	bverror = BVERR_NONE;
+
+exit:
+	/* Unlock access to buffer management. */
+	GCUNLOCK(&gccontext->bufferlock);
+
+	GCEXITARG(GCZONE_BUFFER_ALLOC, "bv%s = %d\n",
+		  (bverror == BVERR_NONE) ? "result" : "error", bverror);
+	return bverror;
+}
+
+static enum bverror allocate_fixup(struct bvbltparams *bvbltparams,
+				   struct gcbuffer *gcbuffer,
+				   struct gcfixup **gcfixup)
+{
+	enum bverror bverror = BVERR_NONE;
+	struct gccontext *gccontext = get_context();
+	struct gcfixup *temp;
+
+	if (list_empty(&gccontext->fixupvac)) {
+		temp = gcalloc(struct gcfixup, sizeof(struct gcfixup));
+		if (temp == NULL) {
+			BVSETBLTERROR(BVERR_OOM, "fixup allocation failed");
+			goto exit;
+		}
+
+		list_add_tail(&temp->link, &gcbuffer->fixup);
+
+		GCDBG(GCZONE_FIXUP_ALLOC,
+		      "new fixup struct allocated = 0x%08X\n",
+		      (unsigned int) temp);
+	} else {
+		struct list_head *head;
+		head = gccontext->fixupvac.next;
+		temp = list_entry(head, struct gcfixup, link);
+
+		list_move_tail(&temp->link, &gcbuffer->fixup);
+
+		GCDBG(GCZONE_FIXUP_ALLOC, "fixup struct reused = 0x%08X\n",
+			(unsigned int) temp);
+	}
+
+	temp->count = 0;
+	*gcfixup = temp;
+
+exit:
+	return bverror;
+}
+
+enum bverror add_fixup(struct bvbltparams *bvbltparams,
+		       struct gcbatch *gcbatch,
+		       unsigned int *ptr,
+		       unsigned int surfoffset)
+{
+	enum bverror bverror = BVERR_NONE;
+	struct gccontext *gccontext = get_context();
+	struct list_head *head;
+	struct gcbuffer *buffer;
+	struct gcfixup *gcfixup;
+
+	GCENTERARG(GCZONE_FIXUP, "batch = 0x%08X, fixup ptr = 0x%08X\n",
+		   (unsigned int) gcbatch, (unsigned int) ptr);
+
+	/* Lock access to fixup management. */
+	GCLOCK(&gccontext->fixuplock);
+
+	/* Get the current command buffer. */
+	if (list_empty(&gcbatch->buffer)) {
+		GCERR("no command buffers are allocated");
+		goto exit;
+	}
+	head = gcbatch->buffer.prev;
+	buffer = list_entry(head, struct gcbuffer, link);
+
+	/* No fixups? Allocate one. */
+	if (list_empty(&buffer->fixup)) {
+		GCDBG(GCZONE_FIXUP_ALLOC, "no fixups allocated.\n");
+		bverror = allocate_fixup(bvbltparams, buffer, &gcfixup);
+		if (bverror != BVERR_NONE)
+			goto exit;
+	} else {
+		/* Get the current fixup. */
+		head = buffer->fixup.prev;
+		gcfixup = list_entry(head, struct gcfixup, link);
+
+		/* No more room? */
+		if (gcfixup->count == GC_FIXUP_MAX) {
+			GCDBG(GCZONE_FIXUP_ALLOC,
+			      "out of room, allocating new.\n");
+			bverror = allocate_fixup(bvbltparams, buffer, &gcfixup);
+			if (bverror != BVERR_NONE)
+				goto exit;
+		}
+	}
+
+	GCDBG(GCZONE_FIXUP, "buffer = 0x%08X, fixup struct = 0x%08X\n",
+	      (unsigned int) buffer, (unsigned int) gcfixup);
+
+	gcfixup->fixup[gcfixup->count].dataoffset = ptr - buffer->head;
+	gcfixup->fixup[gcfixup->count].surfoffset = surfoffset;
+	gcfixup->count += 1;
+
+	GCDBG(GCZONE_FIXUP, "fixup offset = 0x%08X\n", ptr - buffer->head);
+	GCDBG(GCZONE_FIXUP, "surface offset = 0x%08X\n", surfoffset);
+
+exit:
+	/* Unlock access to fixup management. */
+	GCUNLOCK(&gccontext->fixuplock);
+
+	GCEXITARG(GCZONE_FIXUP, "bv%s = %d\n",
+		  (bverror == BVERR_NONE) ? "result" : "error", bverror);
+	return bverror;
+}
+
+enum bverror claim_buffer(struct bvbltparams *bvbltparams,
+			  struct gcbatch *gcbatch,
+			  unsigned int size,
+			  void **buffer)
+{
+	enum bverror bverror;
+	struct list_head *head;
+	struct gcbuffer *gcbuffer;
+
+	GCENTERARG(GCZONE_BUFFER_ALLOC, "batch = 0x%08X, size = %d\n",
+		   (unsigned int) gcbatch, size);
+
+	if (size > GC_BUFFER_INIT_SIZE) {
+		GCERR("requested size is too big.\n");
+		BVSETBLTERROR(BVERR_OOM,
+			      "command buffer allocation failed");
+		goto exit;
+	}
+
+	/* Get the current command buffer. */
+	head = gcbatch->buffer.prev;
+	gcbuffer = list_entry(head, struct gcbuffer, link);
+
+	GCDBG(GCZONE_BUFFER_ALLOC, "buffer = 0x%08X, available = %d\n",
+	      (unsigned int) gcbuffer, gcbuffer->available);
+
+	if (gcbuffer->available < size) {
+		bverror = append_buffer(bvbltparams, gcbatch, &gcbuffer);
+		if (bverror != BVERR_NONE)
+			goto exit;
+	}
+
+	*buffer = gcbuffer->tail;
+	gcbuffer->tail = (unsigned int *)
+			((unsigned char *) gcbuffer->tail + size);
+	gcbuffer->available -= size;
+	gcbatch->size += size;
+	bverror = BVERR_NONE;
+
+exit:
+	GCEXITARG(GCZONE_BUFFER_ALLOC, "bv%s = %d\n",
+		  (bverror == BVERR_NONE) ? "result" : "error", bverror);
+	return bverror;
+}
diff --git a/drivers/misc/gcx/gcbv/gcbv.c b/drivers/misc/gcx/gcbv/gcbv.c
new file mode 100644
index 0000000..de4d074
--- /dev/null
+++ b/drivers/misc/gcx/gcbv/gcbv.c
@@ -0,0 +1,2178 @@
+/*
+ * This file is provided under a dual BSD/GPLv2 license.  When using or
+ * redistributing this file, you may do so under either license.
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * Copyright(c) 2012 Vivante Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * BSD LICENSE
+ *
+ * Copyright(c) 2012 Vivante Corporation. 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 Vivante Corporation 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 AND FITNESS FOR A PARTICULAR PURPOSE
+ * 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.
+ */
+
+#include "gcbv.h"
+
+#define GCZONE_NONE		0
+#define GCZONE_ALL		(~0U)
+#define GCZONE_INIT		(1 << 0)
+#define GCZONE_MAPPING		(1 << 1)
+#define GCZONE_BUFFER		(1 << 2)
+#define GCZONE_DEST		(1 << 3)
+#define GCZONE_SRC		(1 << 4)
+#define GCZONE_MASK		(1 << 5)
+#define GCZONE_BATCH		(1 << 6)
+#define GCZONE_BLIT		(1 << 7)
+#define GCZONE_CACHE		(1 << 8)
+#define GCZONE_CALLBACK		(1 << 9)
+#define GCZONE_TEMP		(1 << 10)
+#define GCZONE_BLEND		(1 << 11)
+
+GCDBG_FILTERDEF(bv, GCZONE_NONE,
+		"init",
+		"mapping",
+		"buffer",
+		"dest",
+		"source",
+		"mask",
+		"batch",
+		"blit",
+		"cache",
+		"callback",
+		"tempbuffer",
+		"blending")
+
+
+/*******************************************************************************
+** Global driver data access.
+*/
+
+struct gccontext *get_context(void)
+{
+	static struct gccontext gccontext;
+	return &gccontext;
+}
+
+
+/*******************************************************************************
+ * Debugging.
+ */
+
+#if GCDEBUG_ENABLE
+#define GCDUMPBATCH(batch) \
+	dumpbatch(batch)
+
+#define GCVERIFYBATCH(changeflags, prevrect, currrect) \
+	verify_batch(changeflags, prevrect, currrect)
+
+static void dumpbatch(struct gcbatch *gcbatch)
+{
+	struct list_head *gcbufferhead;
+	struct gcbuffer *gcbuffer;
+	struct list_head *gcfixuphead;
+	struct gcfixup *gcfixup;
+	unsigned int i, size;
+
+	if ((GCDBGFILTER.zone & (GCZONE_BUFFER)) == 0)
+		return;
+
+	GCDBG(GCZONE_BUFFER, "BATCH DUMP (0x%08X)\n",
+		(unsigned int) gcbatch);
+
+	list_for_each(gcbufferhead, &gcbatch->buffer) {
+		gcbuffer = list_entry(gcbufferhead, struct gcbuffer, link);
+
+		list_for_each(gcfixuphead, &gcbuffer->fixup) {
+			gcfixup = list_entry(gcfixuphead, struct gcfixup, link);
+
+			GCDBG(GCZONE_BUFFER,
+				"  Fixup table @ 0x%08X, count = %d:\n",
+				(unsigned int) gcfixup, gcfixup->count);
+
+			for (i = 0; i < gcfixup->count; i += 1) {
+				GCDBG(GCZONE_BUFFER, "  [%02d]"
+					" buffer offset = 0x%08X,"
+					" surface offset = 0x%08X\n",
+					i,
+					gcfixup->fixup[i].dataoffset * 4,
+					gcfixup->fixup[i].surfoffset);
+			}
+		}
+
+		size = (unsigned char *) gcbuffer->tail
+		     - (unsigned char *) gcbuffer->head;
+		GCDUMPBUFFER(GCZONE_BUFFER, gcbuffer->head, 0, size);
+	}
+}
+
+static void verify_batch(unsigned int changeflags,
+				struct bvrect *prevrect,
+				struct bvrect *currrect)
+{
+	if ((changeflags & 1) == 0) {
+		/* Origin did not change. */
+		if ((prevrect->left != currrect->left) ||
+			(prevrect->top != currrect->top)) {
+			GCERR("origin changed\n");
+			GCERR("  previous = %d,%d\n",
+				prevrect->left, prevrect->top);
+			GCERR("  current = %d,%d\n",
+				currrect->left, currrect->top);
+		}
+	}
+
+	if ((changeflags & 2) == 0) {
+		/* Size did not change. */
+		if ((prevrect->width != currrect->width) ||
+			(prevrect->height != currrect->height)) {
+			GCERR("size changed\n");
+			GCERR("  previous = %dx%d\n",
+				prevrect->width, prevrect->height);
+			GCERR("  current = %dx%d\n",
+				currrect->width, currrect->height);
+		}
+	}
+
+	prevrect->left = currrect->left;
+	prevrect->top = currrect->top;
+	prevrect->width = currrect->width;
+	prevrect->height = currrect->height;
+}
+#else
+#define GCDUMPBATCH(...)
+#define GCVERIFYBATCH(...)
+#endif
+
+
+/*******************************************************************************
+ * Error handling.
+ */
+
+#define BVSETBLTSURFERROR(errorid, errordesc) \
+do { \
+	struct gccontext *tmpcontext = get_context(); \
+	snprintf(tmpcontext->bverrorstr, sizeof(tmpcontext->bverrorstr), \
+		 g_surferr[errorid].message, errordesc.id); \
+	GCDUMPSTRING("%s(%d): [ERROR] %s\n", __func__, __LINE__, \
+		     tmpcontext->bverrorstr); \
+	bverror = errordesc.base + g_surferr[errorid].offset; \
+	bvbltparams->errdesc = tmpcontext->bverrorstr; \
+} while (0)
+
+#define GCBVERR_DESC		0
+#define GCBVERR_DESC_VERS	1
+#define GCBVERR_DESC_VIRTADDR	2
+#define GCBVERR_TILE		3
+#define GCBVERR_TILE_VERS	4
+#define GCBVERR_TILE_VIRTADDR	5
+#define GCBVERR_GEOM		6
+#define GCBVERR_GEOM_VERS	7
+#define GCBVERR_GEOM_FORMAT	8
+
+struct bvsurferrorid {
+	char *id;
+	enum bverror base;
+};
+
+struct bvsurferror {
+	unsigned int offset;
+	char *message;
+};
+
+static struct bvsurferror g_surferr[] = {
+	/* GCBVERR_DESC */
+	{    0, "%s desc structure is not set" },
+
+	/* GCBVERR_DESC_VERS */
+	{  100, "%s desc structure has invalid size" },
+
+	/* GCBVERR_DESC_VIRTADDR */
+	{  200, "%s desc virtual pointer is not set" },
+
+	/* GCBVERR_TILE: FIXME/TODO define error code */
+	{    0, "%s tileparams structure is not set" },
+
+	/* GCBVERR_TILE_VERS */
+	{ 3000, "%s tileparams structure has invalid size" },
+
+	/* GCBVERR_TILE_VIRTADDR: FIXME/TODO define error code */
+	{  200, "%s tileparams virtual pointer is not set" },
+
+	/* GCBVERR_GEOM */
+	{ 1000, "%s geom structure is not set" },
+
+	/* GCBVERR_GEOM_VERS */
+	{ 1100, "%s geom structure has invalid size" },
+
+	/* GCBVERR_GEOM_FORMAT */
+	{ 1200, "%s invalid format specified" },
+};
+
+static struct bvsurferrorid g_destsurferr = { "dst",  BVERR_DSTDESC };
+static struct bvsurferrorid g_src1surferr = { "src1", BVERR_SRC1DESC };
+static struct bvsurferrorid g_src2surferr = { "src2", BVERR_SRC2DESC };
+static struct bvsurferrorid g_masksurferr = { "mask", BVERR_MASKDESC };
+
+
+/*******************************************************************************
+ * Callback info management.
+ */
+
+/* BLTsville callback function. */
+struct gccallbackbltsville {
+	/* Function pointer. */
+	void (*fn) (struct bvcallbackerror *err, unsigned long callbackdata);
+
+	/* Callback data. */
+	unsigned long data;
+};
+
+/* Information for freeing a surface. */
+struct gccallbackfreesurface {
+	/* Pointer to the buffer descriptor. */
+	struct bvbuffdesc *desc;
+
+	/* Pointer to the buffer. */
+	void *ptr;
+};
+
+/* Callback information. */
+struct gccallbackinfo {
+	union {
+		/* BLTsville callback function. */
+		struct gccallbackbltsville callback;
+
+		/* Information for freeing a surface. */
+		struct gccallbackfreesurface freesurface;
+	} info;
+
+	/* Previous/next callback information. */
+	struct list_head link;
+};
+
+static enum bverror get_callbackinfo(struct gccallbackinfo **gccallbackinfo)
+{
+	enum bverror bverror;
+	struct gccontext *gccontext = get_context();
+	struct gccallbackinfo *temp;
+
+	/* Lock access to callback info lists. */
+	GCLOCK(&gccontext->callbacklock);
+
+	if (list_empty(&gccontext->callbackvac)) {
+		temp = gcalloc(struct gccallbackinfo,
+			       sizeof(struct gccallbackinfo));
+		if (temp == NULL) {
+			bverror = BVERR_OOM;
+			goto exit;
+		}
+		list_add(&temp->link, &gccontext->callbacklist);
+	} else {
+		struct list_head *head;
+		head = gccontext->callbackvac.next;
+		temp = list_entry(head, struct gccallbackinfo, link);
+		list_move(head, &gccontext->callbacklist);
+	}
+
+	*gccallbackinfo = temp;
+	bverror = BVERR_NONE;
+
+exit:
+	/* Unlock access to callback info lists. */
+	GCUNLOCK(&gccontext->callbacklock);
+
+	return bverror;
+}
+
+static void free_callback(struct gccallbackinfo *gccallbackinfo)
+{
+	struct gccontext *gccontext = get_context();
+
+	/* Lock access to callback info lists. */
+	GCLOCK(&gccontext->callbacklock);
+
+	list_move(&gccallbackinfo->link, &gccontext->callbackvac);
+
+	/* Unlock access to callback info lists. */
+	GCUNLOCK(&gccontext->callbacklock);
+}
+
+void callbackbltsville(void *callbackinfo)
+{
+	struct gccallbackinfo *gccallbackinfo;
+
+	GCENTER(GCZONE_CALLBACK);
+
+	gccallbackinfo = (struct gccallbackinfo *) callbackinfo;
+	GCDBG(GCZONE_CALLBACK, "bltsville_callback = 0x%08X\n",
+	      (unsigned int) gccallbackinfo->info.callback.fn);
+	GCDBG(GCZONE_CALLBACK, "bltsville_param    = 0x%08X\n",
+	      (unsigned int) gccallbackinfo->info.callback.data);
+
+	gccallbackinfo->info.callback.fn(NULL,
+					 gccallbackinfo->info.callback.data);
+	free_callback(gccallbackinfo);
+
+	GCEXIT(GCZONE_CALLBACK);
+}
+
+void callbackfreesurface(void *callbackinfo)
+{
+	struct gccallbackinfo *gccallbackinfo;
+
+	GCENTER(GCZONE_CALLBACK);
+
+	gccallbackinfo = (struct gccallbackinfo *) callbackinfo;
+	GCDBG(GCZONE_CALLBACK, "freeing descriptir @ 0x%08X\n",
+	      (unsigned int) gccallbackinfo->info.freesurface.desc);
+	GCDBG(GCZONE_CALLBACK, "freeing memory @ 0x%08X\n",
+	      (unsigned int) gccallbackinfo->info.freesurface.ptr);
+
+	free_surface(gccallbackinfo->info.freesurface.desc,
+		     gccallbackinfo->info.freesurface.ptr);
+	free_callback(gccallbackinfo);
+
+	GCEXIT(GCZONE_CALLBACK);
+}
+
+
+/*******************************************************************************
+ * Temporary buffer management.
+ */
+
+enum bverror allocate_temp(struct bvbltparams *bvbltparams,
+			   unsigned int size)
+{
+	enum bverror bverror;
+	struct gccontext *gccontext = get_context();
+
+	GCENTER(GCZONE_TEMP);
+
+	/* Existing buffer too small? */
+	if ((gccontext->tmpbuffdesc != NULL) &&
+	    (gccontext->tmpbuffdesc->length < size)) {
+		GCDBG(GCZONE_TEMP, "freeing current buffer.\n");
+		bverror = free_temp(true);
+		if (bverror != BVERR_NONE) {
+			bvbltparams->errdesc = gccontext->bverrorstr;
+			goto exit;
+		}
+	}
+
+	/* Allocate new buffer if necessary. */
+	if ((size > 0) && (gccontext->tmpbuffdesc == NULL)) {
+		/* Allocate temporary surface. */
+		bverror = allocate_surface(&gccontext->tmpbuffdesc,
+					   &gccontext->tmpbuff,
+					   size);
+		if (bverror != BVERR_NONE) {
+			bvbltparams->errdesc = gccontext->bverrorstr;
+			goto exit;
+		}
+
+		GCDBG(GCZONE_TEMP, "buffdesc @ 0x%08X\n",
+		      gccontext->tmpbuffdesc);
+		GCDBG(GCZONE_TEMP, "allocated @ 0x%08X\n",
+		      gccontext->tmpbuff);
+		GCDBG(GCZONE_TEMP, "size = %d\n",
+		      size);
+
+		/* Map the buffer explicitly. */
+		bverror = bv_map(gccontext->tmpbuffdesc);
+		if (bverror != BVERR_NONE) {
+			bvbltparams->errdesc = gccontext->bverrorstr;
+			goto exit;
+		}
+	}
+
+	/* Success. */
+	bverror = BVERR_NONE;
+
+exit:
+	GCEXIT(GCZONE_TEMP);
+	return bverror;
+}
+
+enum bverror free_temp(bool schedule)
+{
+	enum bverror bverror;
+	struct gccontext *gccontext = get_context();
+	struct gccallbackinfo *gccallbackinfo;
+	struct gcicallbackarm gcicallbackarm;
+
+	/* Is the buffer allocated? */
+	if (gccontext->tmpbuffdesc == NULL) {
+		bverror = BVERR_NONE;
+		goto exit;
+	}
+
+	/* Unmap the buffer. */
+	bverror = bv_unmap(gccontext->tmpbuffdesc);
+	if (bverror != BVERR_NONE)
+		goto exit;
+
+	/* Cannot be mapped. */
+	if (gccontext->tmpbuffdesc->map != NULL) {
+		BVSETERROR(BVERR_OOM, "temporary buffer is still mapped");
+		goto exit;
+	}
+
+	/* Free the buffer. */
+	if (schedule) {
+		bverror = get_callbackinfo(&gccallbackinfo);
+		if (bverror != BVERR_NONE) {
+			BVSETERROR(BVERR_OOM,
+				   "callback allocation failed");
+			goto exit;
+		}
+
+		gccallbackinfo->info.freesurface.desc = gccontext->tmpbuffdesc;
+		gccallbackinfo->info.freesurface.ptr = gccontext->tmpbuff;
+		gcicallbackarm.callback = callbackfreesurface;
+		gcicallbackarm.callbackparam = gccallbackinfo;
+
+		/* Schedule to free the buffer. */
+		gc_callback_wrapper(&gcicallbackarm);
+
+		/* Error? */
+		if (gcicallbackarm.gcerror != GCERR_NONE) {
+			BVSETERROR(BVERR_OOM, "unable to schedule callback");
+			goto exit;
+		}
+	} else {
+		/* Free the buffer immediately. */
+		free_surface(gccontext->tmpbuffdesc, gccontext->tmpbuff);
+	}
+
+	/* Reset the buffer descriptor. */
+	gccontext->tmpbuffdesc = NULL;
+	gccontext->tmpbuff = NULL;
+
+exit:
+	return bverror;
+}
+
+
+/*******************************************************************************
+ * Program the destination.
+ */
+
+enum bverror set_dst(struct bvbltparams *bvbltparams,
+		     struct gcbatch *batch,
+		     struct bvbuffmap *dstmap)
+{
+	enum bverror bverror = BVERR_NONE;
+	struct gcsurface *dstinfo;
+	struct gcmodst *gcmodst;
+
+	GCENTER(GCZONE_DEST);
+
+	/* Get a shortcut to the destination surface descriptor. */
+	dstinfo = &batch->dstinfo;
+
+	/* Did destination surface change? */
+	if (dstinfo->surfdirty) {
+		/* Allocate command buffer. */
+		bverror = claim_buffer(bvbltparams, batch,
+				       sizeof(struct gcmodst),
+				       (void **) &gcmodst);
+		if (bverror != BVERR_NONE)
+			goto exit;
+
+		/* Add the address fixup. */
+		add_fixup(bvbltparams, batch, &gcmodst->address,
+			  dstinfo->bytealign1);
+
+		/* Set surface parameters. */
+		gcmodst->config_ldst = gcmodst_config_ldst;
+		gcmodst->address = GET_MAP_HANDLE(dstmap);
+		gcmodst->stride = dstinfo->stride1;
+
+		/* Set surface width and height. */
+		gcmodst->rotation.raw = 0;
+		gcmodst->rotation.reg.surf_width = dstinfo->physwidth;
+		gcmodst->rotationheight_ldst = gcmodst_rotationheight_ldst;
+		gcmodst->rotationheight.raw = 0;
+		gcmodst->rotationheight.reg.height = dstinfo->physheight;
+
+		/* Disable hardware clipping. */
+		gcmodst->clip_ldst = gcmodst_clip_ldst;
+		gcmodst->cliplt.raw = 0;
+		gcmodst->cliprb.raw = 0;
+		gcmodst->cliprb.reg.right = GC_CLIP_RESET_RIGHT;
+		gcmodst->cliprb.reg.bottom = GC_CLIP_RESET_BOTTOM;
+	}
+
+exit:
+	GCEXITARG(GCZONE_DEST, "bv%s = %d\n",
+		  (bverror == BVERR_NONE) ? "result" : "error", bverror);
+	return bverror;
+}
+
+
+/*******************************************************************************
+ * Program blending.
+ */
+
+enum bverror set_blending(struct bvbltparams *bvbltparams,
+			  struct gcbatch *batch,
+			  struct gcsurface *srcinfo)
+{
+	enum bverror bverror = BVERR_NONE;
+	struct gcmoalphaoff *gcmoalphaoff;
+	struct gcmoalpha *gcmoalpha;
+	struct gcmoglobal *gcmoglobal;
+	struct gcalpha *gca;
+
+	GCENTER(GCZONE_BLEND);
+
+	gca = srcinfo->gca;
+	if (gca == NULL) {
+		bverror = claim_buffer(bvbltparams, batch,
+				       sizeof(struct gcmoalphaoff),
+				       (void **) &gcmoalphaoff);
+		if (bverror != BVERR_NONE)
+			goto exit;
+
+		gcmoalphaoff->control_ldst = gcmoalphaoff_control_ldst[0];
+		gcmoalphaoff->control.reg = gcregalpha_off;
+
+		GCDBG(GCZONE_BLEND, "blending disabled.\n");
+	} else {
+		bverror = claim_buffer(bvbltparams, batch,
+				       sizeof(struct gcmoalpha),
+				       (void **) &gcmoalpha);
+		if (bverror != BVERR_NONE)
+			goto exit;
+
+		gcmoalpha->config_ldst = gcmoalpha_config_ldst;
+		gcmoalpha->control.reg = gcregalpha_on;
+
+		gcmoalpha->mode.raw = 0;
+		gcmoalpha->mode.reg.src_global_alpha_mode
+			= srcinfo->srcglobalmode;
+		gcmoalpha->mode.reg.dst_global_alpha_mode
+			= srcinfo->dstglobalmode;
+
+		gcmoalpha->mode.reg.src_blend
+			= gca->srcconfig->factor_mode;
+		gcmoalpha->mode.reg.src_color_reverse
+			= gca->srcconfig->color_reverse;
+
+		gcmoalpha->mode.reg.dst_blend
+			= gca->dstconfig->factor_mode;
+		gcmoalpha->mode.reg.dst_color_reverse
+			= gca->dstconfig->color_reverse;
+
+		GCDBG(GCZONE_BLEND, "dst blend:\n");
+		GCDBG(GCZONE_BLEND, "  factor = %d\n",
+			gcmoalpha->mode.reg.dst_blend);
+		GCDBG(GCZONE_BLEND, "  inverse = %d\n",
+			gcmoalpha->mode.reg.dst_color_reverse);
+
+		GCDBG(GCZONE_BLEND, "src blend:\n");
+		GCDBG(GCZONE_BLEND, "  factor = %d\n",
+			gcmoalpha->mode.reg.src_blend);
+		GCDBG(GCZONE_BLEND, "  inverse = %d\n",
+			gcmoalpha->mode.reg.src_color_reverse);
+	}
+
+	if (srcinfo->globalcolorenable) {
+		bverror = claim_buffer(bvbltparams, batch,
+				       sizeof(struct gcmoglobal),
+				       (void **) &gcmoglobal);
+		if (bverror != BVERR_NONE)
+			goto exit;
+
+		gcmoglobal->color_ldst = gcmoglobal_color_ldst;
+		gcmoglobal->srcglobal.raw = srcinfo->globalcolor;
+		gcmoglobal->dstglobal.raw = srcinfo->globalcolor;
+	}
+
+exit:
+	GCEXITARG(GCZONE_BLEND, "bv%s = %d\n",
+		  (bverror == BVERR_NONE) ? "result" : "error", bverror);
+	return bverror;
+}
+
+enum bverror set_blending_index(struct bvbltparams *bvbltparams,
+				struct gcbatch *batch,
+				struct gcsurface *srcinfo,
+				unsigned int index)
+{
+	enum bverror bverror = BVERR_NONE;
+	struct gcmoalphaoff *gcmoalphaoff;
+	struct gcmoxsrcalpha *gcmoxsrcalpha;
+	struct gcmoxsrcglobal *gcmoxsrcglobal;
+	struct gcalpha *gca;
+
+	GCENTER(GCZONE_BLEND);
+
+	gca = srcinfo->gca;
+	if (gca == NULL) {
+		bverror = claim_buffer(bvbltparams, batch,
+				       sizeof(struct gcmoalphaoff),
+				       (void **) &gcmoalphaoff);
+		if (bverror != BVERR_NONE)
+			goto exit;
+
+		gcmoalphaoff->control_ldst = gcmoalphaoff_control_ldst[index];
+		gcmoalphaoff->control.reg = gcregalpha_off;
+
+		GCDBG(GCZONE_BLEND, "blending disabled.\n");
+	} else {
+		bverror = claim_buffer(bvbltparams, batch,
+				       sizeof(struct gcmoxsrcalpha),
+				       (void **) &gcmoxsrcalpha);
+		if (bverror != BVERR_NONE)
+			goto exit;
+
+		gcmoxsrcalpha->control_ldst = gcmoxsrcalpha_control_ldst[index];
+		gcmoxsrcalpha->control.reg = gcregalpha_on;
+
+		gcmoxsrcalpha->mode_ldst = gcmoxsrcalpha_mode_ldst[index];
+		gcmoxsrcalpha->mode.raw = 0;
+		gcmoxsrcalpha->mode.reg.src_global_alpha_mode
+			= srcinfo->srcglobalmode;
+		gcmoxsrcalpha->mode.reg.dst_global_alpha_mode
+			= srcinfo->dstglobalmode;
+
+		gcmoxsrcalpha->mode.reg.src_blend
+			= gca->srcconfig->factor_mode;
+		gcmoxsrcalpha->mode.reg.src_color_reverse
+			= gca->srcconfig->color_reverse;
+
+		gcmoxsrcalpha->mode.reg.dst_blend
+			= gca->dstconfig->factor_mode;
+		gcmoxsrcalpha->mode.reg.dst_color_reverse
+			= gca->dstconfig->color_reverse;
+
+		GCDBG(GCZONE_BLEND, "dst blend:\n");
+		GCDBG(GCZONE_BLEND, "  factor = %d\n",
+			gcmoxsrcalpha->mode.reg.dst_blend);
+		GCDBG(GCZONE_BLEND, "  inverse = %d\n",
+			gcmoxsrcalpha->mode.reg.dst_color_reverse);
+
+		GCDBG(GCZONE_BLEND, "src blend:\n");
+		GCDBG(GCZONE_BLEND, "  factor = %d\n",
+			gcmoxsrcalpha->mode.reg.src_blend);
+		GCDBG(GCZONE_BLEND, "  inverse = %d\n",
+			gcmoxsrcalpha->mode.reg.src_color_reverse);
+	}
+
+	if (srcinfo->globalcolorenable) {
+		bverror = claim_buffer(bvbltparams, batch,
+				       sizeof(struct gcmoxsrcglobal),
+				       (void **) &gcmoxsrcglobal);
+		if (bverror != BVERR_NONE)
+			goto exit;
+
+		gcmoxsrcglobal->srcglobal_ldst
+			= gcmoxsrcglobal_srcglobal_ldst[index];
+		gcmoxsrcglobal->srcglobal.raw = srcinfo->globalcolor;
+
+		gcmoxsrcglobal->dstglobal_ldst
+			= gcmoxsrcglobal_dstglobal_ldst[index];
+		gcmoxsrcglobal->dstglobal.raw = srcinfo->globalcolor;
+	}
+
+exit:
+	GCEXITARG(GCZONE_BLEND, "bv%s = %d\n",
+		  (bverror == BVERR_NONE) ? "result" : "error", bverror);
+	return bverror;
+}
+
+/*******************************************************************************
+ * Program YUV source.
+ */
+
+void set_computeyuv(struct gcsurface *srcinfo, int x, int y)
+{
+	int pixalign, bytealign;
+	unsigned int height1, size1;
+	unsigned int height2, size2;
+	unsigned int origin;
+	int ssX, ssY;
+
+	GCENTER(GCZONE_SRC);
+
+	/* Compute base address alignment. */
+	pixalign = get_pixel_offset(srcinfo, 0);
+	bytealign = (pixalign * (int) srcinfo->format.bitspp) / 8;
+
+	/* Determine the physical height of the first plane. */
+	height1 = ((srcinfo->angle % 2) == 0)
+		? srcinfo->height
+		: srcinfo->width;
+
+	/* Determine the size of the first plane. */
+	size1 = srcinfo->stride1 * height1;
+
+	/* Determine the stride of the second plane. */
+	srcinfo->stride2 = srcinfo->stride1
+			 / srcinfo->format.cs.yuv.xsample;
+
+	/* Determine subsample pixel position. */
+	ssX = x / srcinfo->format.cs.yuv.xsample;
+	ssY = y / srcinfo->format.cs.yuv.ysample;
+
+	switch (srcinfo->format.cs.yuv.planecount) {
+	case 2:
+		/* U and V are interleaved in one plane. */
+		ssX *= 2;
+		srcinfo->stride2 *= 2;
+
+		/* Determnine the origin offset. */
+		origin = ssY * srcinfo->stride2 + ssX;
+
+		/* Compute the alignment of the second plane. */
+		srcinfo->bytealign2 = bytealign + size1 + origin;
+
+		GCDBG(GCZONE_SRC, "plane2 offset (bytes) = 0x%08X\n",
+			srcinfo->bytealign2);
+		GCDBG(GCZONE_SRC, "plane2 stride = %d\n",
+			srcinfo->stride2);
+		break;
+
+	case 3:
+		/* Determine the physical height of the U/V planes. */
+		height2 = height1 / srcinfo->format.cs.yuv.ysample;
+
+		/* Determine the size of the U/V planes. */
+		size2 = srcinfo->stride2 * height2;
+
+		/* Determnine the origin offset. */
+		origin = ssY * srcinfo->stride2 + ssX;
+
+		/* Compute the alignment of the U/V planes. */
+		srcinfo->bytealign2 = bytealign + size1 + origin;
+		srcinfo->bytealign3 = bytealign + size1 + size2 + origin;
+
+		/* Determine the stride of the U/V planes. */
+		srcinfo->stride3 = srcinfo->stride2;
+
+		GCDBG(GCZONE_SRC, "plane2 offset (bytes) = 0x%08X\n",
+		      srcinfo->bytealign2);
+		GCDBG(GCZONE_SRC, "plane2 stride = %d\n",
+			srcinfo->stride2);
+		GCDBG(GCZONE_SRC, "plane3 offset (bytes) = 0x%08X\n",
+		      srcinfo->bytealign3);
+		GCDBG(GCZONE_SRC, "plane3 stride = %d\n",
+			srcinfo->stride3);
+		break;
+	}
+
+	GCEXIT(GCZONE_SRC);
+}
+
+enum bverror set_yuvsrc(struct bvbltparams *bvbltparams,
+			struct gcbatch *batch,
+			struct gcsurface *srcinfo,
+			struct bvbuffmap *srcmap)
+{
+	enum bverror bverror = BVERR_NONE;
+	struct gcmoyuv1 *gcmoyuv1;
+	struct gcmoyuv2 *gcmoyuv2;
+	struct gcmoyuv3 *gcmoyuv3;
+
+	GCENTER(GCZONE_SRC);
+
+	GCDBG(GCZONE_SRC, "plane count %d.\n",
+	      srcinfo->format.cs.yuv.planecount);
+
+	switch (srcinfo->format.cs.yuv.planecount) {
+	case 1:
+		bverror = claim_buffer(bvbltparams, batch,
+				       sizeof(struct gcmoyuv1),
+				       (void **) &gcmoyuv1);
+		if (bverror != BVERR_NONE)
+			goto exit;
+
+		/* Set YUV parameters. */
+		gcmoyuv1->pectrl_ldst = gcmoyuv_pectrl_ldst;
+		gcmoyuv1->pectrl.raw = 0;
+		gcmoyuv1->pectrl.reg.standard
+			= srcinfo->format.cs.yuv.std;
+		gcmoyuv1->pectrl.reg.swizzle
+			= srcinfo->format.swizzle;
+		gcmoyuv1->pectrl.reg.convert
+			= GCREG_PE_CONTROL_YUVRGB_DISABLED;
+		break;
+
+	case 2:
+		bverror = claim_buffer(bvbltparams, batch,
+					sizeof(struct gcmoyuv2),
+					(void **) &gcmoyuv2);
+		if (bverror != BVERR_NONE)
+			goto exit;
+
+		/* Set YUV parameters. */
+		gcmoyuv2->pectrl_ldst = gcmoyuv_pectrl_ldst;
+		gcmoyuv2->pectrl.raw = 0;
+		gcmoyuv2->pectrl.reg.standard
+			= srcinfo->format.cs.yuv.std;
+		gcmoyuv2->pectrl.reg.swizzle
+			= srcinfo->format.swizzle;
+		gcmoyuv2->pectrl.reg.convert
+			= GCREG_PE_CONTROL_YUVRGB_DISABLED;
+
+		/* Program U/V plane. */
+		add_fixup(bvbltparams, batch, &gcmoyuv2->uplaneaddress,
+			  srcinfo->bytealign2);
+		gcmoyuv2->plane_ldst = gcmoyuv2_plane_ldst;
+		gcmoyuv2->uplaneaddress = GET_MAP_HANDLE(srcmap);
+		gcmoyuv2->uplanestride = srcinfo->stride2;
+		break;
+
+	case 3:
+		bverror = claim_buffer(bvbltparams, batch,
+					sizeof(struct gcmoyuv3),
+					(void **) &gcmoyuv3);
+		if (bverror != BVERR_NONE)
+			goto exit;
+
+		/* Set YUV parameters. */
+		gcmoyuv3->pectrl_ldst = gcmoyuv_pectrl_ldst;
+		gcmoyuv3->pectrl.raw = 0;
+		gcmoyuv3->pectrl.reg.standard
+			= srcinfo->format.cs.yuv.std;
+		gcmoyuv3->pectrl.reg.swizzle
+			= srcinfo->format.swizzle;
+		gcmoyuv3->pectrl.reg.convert
+			= GCREG_PE_CONTROL_YUVRGB_DISABLED;
+
+		/* Program U/V planes. */
+		add_fixup(bvbltparams, batch, &gcmoyuv3->uplaneaddress,
+			  srcinfo->bytealign2);
+		add_fixup(bvbltparams, batch, &gcmoyuv3->vplaneaddress,
+			  srcinfo->bytealign3);
+		gcmoyuv3->plane_ldst = gcmoyuv3_plane_ldst;
+		gcmoyuv3->uplaneaddress = GET_MAP_HANDLE(srcmap);
+		gcmoyuv3->uplanestride  = srcinfo->stride2;
+		gcmoyuv3->vplaneaddress = GET_MAP_HANDLE(srcmap);
+		gcmoyuv3->vplanestride  = srcinfo->stride3;
+		break;
+
+	default:
+		GCERR("invlaid plane count %d.\n",
+		      srcinfo->format.cs.yuv.planecount);
+	}
+
+exit:
+	GCEXITARG(GCZONE_SRC, "bv%s = %d\n",
+		  (bverror == BVERR_NONE) ? "result" : "error", bverror);
+	return bverror;
+}
+
+enum bverror set_yuvsrc_index(struct bvbltparams *bvbltparams,
+			      struct gcbatch *batch,
+			      struct gcsurface *srcinfo,
+			      struct bvbuffmap *srcmap,
+			      unsigned int index)
+{
+	enum bverror bverror = BVERR_NONE;
+	struct gcmoxsrcyuv1 *gcmoxsrcyuv1;
+	struct gcmoxsrcyuv2 *gcmoxsrcyuv2;
+	struct gcmoxsrcyuv3 *gcmoxsrcyuv3;
+
+	GCENTER(GCZONE_SRC);
+
+	GCDBG(GCZONE_SRC, "plane count %d.\n",
+	      srcinfo->format.cs.yuv.planecount);
+
+	switch (srcinfo->format.cs.yuv.planecount) {
+	case 1:
+		bverror = claim_buffer(bvbltparams, batch,
+				       sizeof(struct gcmoxsrcyuv1),
+				       (void **) &gcmoxsrcyuv1);
+		if (bverror != BVERR_NONE)
+			goto exit;
+
+		/* Set YUV parameters. */
+		gcmoxsrcyuv1->pectrl_ldst
+			= gcmoxsrcyuv_pectrl_ldst[index];
+		gcmoxsrcyuv1->pectrl.raw = 0;
+		gcmoxsrcyuv1->pectrl.reg.standard
+			= srcinfo->format.cs.yuv.std;
+		gcmoxsrcyuv1->pectrl.reg.swizzle
+			= srcinfo->format.swizzle;
+		gcmoxsrcyuv1->pectrl.reg.convert
+			= GCREG_PE_CONTROL_YUVRGB_DISABLED;
+		break;
+
+	case 2:
+		bverror = claim_buffer(bvbltparams, batch,
+					sizeof(struct gcmoxsrcyuv2),
+					(void **) &gcmoxsrcyuv2);
+		if (bverror != BVERR_NONE)
+			goto exit;
+
+		/* Set YUV parameters. */
+		gcmoxsrcyuv2->pectrl_ldst
+			= gcmoxsrcyuv_pectrl_ldst[index];
+		gcmoxsrcyuv2->pectrl.raw = 0;
+		gcmoxsrcyuv2->pectrl.reg.standard
+			= srcinfo->format.cs.yuv.std;
+		gcmoxsrcyuv2->pectrl.reg.swizzle
+			= srcinfo->format.swizzle;
+		gcmoxsrcyuv2->pectrl.reg.convert
+			= GCREG_PE_CONTROL_YUVRGB_DISABLED;
+
+		/* Program U/V plane. */
+		add_fixup(bvbltparams, batch, &gcmoxsrcyuv2->uplaneaddress,
+			  srcinfo->bytealign2);
+		gcmoxsrcyuv2->uplaneaddress_ldst
+			= gcmoxsrcyuv_uplaneaddress_ldst[index];
+		gcmoxsrcyuv2->uplaneaddress = GET_MAP_HANDLE(srcmap);
+		gcmoxsrcyuv2->uplanestride_ldst
+			= gcmoxsrcyuv_uplanestride_ldst[index];
+		gcmoxsrcyuv2->uplanestride = srcinfo->stride2;
+		break;
+
+	case 3:
+		bverror = claim_buffer(bvbltparams, batch,
+					sizeof(struct gcmoxsrcyuv3),
+					(void **) &gcmoxsrcyuv3);
+		if (bverror != BVERR_NONE)
+			goto exit;
+
+		/* Set YUV parameters. */
+		gcmoxsrcyuv3->pectrl_ldst
+			= gcmoxsrcyuv_pectrl_ldst[index];
+		gcmoxsrcyuv3->pectrl.raw = 0;
+		gcmoxsrcyuv3->pectrl.reg.standard
+			= srcinfo->format.cs.yuv.std;
+		gcmoxsrcyuv3->pectrl.reg.swizzle
+			= srcinfo->format.swizzle;
+		gcmoxsrcyuv3->pectrl.reg.convert
+			= GCREG_PE_CONTROL_YUVRGB_DISABLED;
+
+		/* Program U/V planes. */
+		add_fixup(bvbltparams, batch, &gcmoxsrcyuv3->uplaneaddress,
+			  srcinfo->bytealign2);
+		add_fixup(bvbltparams, batch, &gcmoxsrcyuv3->vplaneaddress,
+			  srcinfo->bytealign3);
+		gcmoxsrcyuv3->uplaneaddress_ldst
+			= gcmoxsrcyuv_uplaneaddress_ldst[index];
+		gcmoxsrcyuv3->uplaneaddress = GET_MAP_HANDLE(srcmap);
+		gcmoxsrcyuv3->uplanestride_ldst
+			= gcmoxsrcyuv_uplanestride_ldst[index];
+		gcmoxsrcyuv3->uplanestride  = srcinfo->stride2;
+		gcmoxsrcyuv3->vplaneaddress_ldst
+			= gcmoxsrcyuv_vplaneaddress_ldst[index];
+		gcmoxsrcyuv3->vplaneaddress = GET_MAP_HANDLE(srcmap);
+		gcmoxsrcyuv3->vplanestride_ldst
+			= gcmoxsrcyuv_vplanestride_ldst[index];
+		gcmoxsrcyuv3->vplanestride  = srcinfo->stride3;
+		break;
+
+	default:
+		GCERR("invlaid plane count %d.\n",
+		      srcinfo->format.cs.yuv.planecount);
+	}
+
+exit:
+	GCEXITARG(GCZONE_SRC, "bv%s = %d\n",
+		  (bverror == BVERR_NONE) ? "result" : "error", bverror);
+	return bverror;
+}
+
+
+/*******************************************************************************
+ * Surface compare and validation.
+ */
+
+static inline bool equal_rects(struct bvrect *rect1, struct bvrect *rect2)
+{
+	if (rect1->left != rect2->left)
+		return false;
+
+	if (rect1->top != rect2->top)
+		return false;
+
+	if (rect1->width != rect2->width)
+		return false;
+
+	if (rect1->height != rect2->height)
+		return false;
+
+	return true;
+}
+
+/* The function verifies whether the two buffer descriptors and rectangles
+   define the same physical area. */
+static bool same_phys_area(struct bvbuffdesc *surf1, struct bvrect *rect1,
+			   struct bvbuffdesc *surf2, struct bvrect *rect2)
+{
+	struct bvphysdesc *physdesc1;
+	struct bvphysdesc *physdesc2;
+
+	/* If pointers are the same, things are much easier. */
+	if (surf1 == surf2)
+		/* Compare the rectangles. For simplicity we don't consider
+		   cases with partially overlapping rectangles at this time. */
+		return equal_rects(rect1, rect2);
+
+	/* Assume diffrent areas if the types are different. */
+	if (surf1->auxtype != surf2->auxtype)
+		return false;
+
+	if (surf1->auxtype == BVAT_PHYSDESC) {
+		physdesc1 = (struct bvphysdesc *) surf1->auxptr;
+		physdesc2 = (struct bvphysdesc *) surf2->auxptr;
+
+		/* Same physical descriptor? */
+		if (physdesc1 == physdesc2)
+			return equal_rects(rect1, rect2);
+
+		/* Same page array? */
+		if (physdesc1->pagearray == physdesc2->pagearray)
+			return equal_rects(rect1, rect2);
+
+		/* Pageoffsets must match since different buffers
+		 * can share the same first page (eg nv12).
+		 */
+		if (physdesc1->pageoffset != physdesc2->pageoffset)
+			return false;
+
+		/* Assume the same surface if first pages match. */
+		if (physdesc1->pagearray[0] == physdesc2->pagearray[0])
+			return equal_rects(rect1, rect2);
+
+	} else {
+		if (surf1->virtaddr == surf2->virtaddr)
+			return equal_rects(rect1, rect2);
+	}
+
+	return false;
+}
+
+static int verify_surface(unsigned int tile,
+			  union bvinbuff *surf,
+			  struct bvsurfgeom *geom)
+{
+	if (tile) {
+		if (surf->tileparams == NULL)
+			return GCBVERR_TILE;
+
+		if (surf->tileparams->structsize <
+		    STRUCTSIZE(surf->tileparams, srcheight))
+			return GCBVERR_TILE_VERS;
+
+		/* FIXME/TODO */
+		return GCBVERR_TILE;
+	} else {
+		if (surf->desc == NULL)
+			return GCBVERR_DESC;
+
+		if (surf->desc->structsize < STRUCTSIZE(surf->desc, map))
+			return GCBVERR_DESC_VERS;
+	}
+
+	if (geom == NULL)
+		return GCBVERR_GEOM;
+
+	if (geom->structsize < STRUCTSIZE(geom, palette))
+		return GCBVERR_GEOM_VERS;
+
+	/* Validation successful. */
+	return -1;
+}
+
+
+/*******************************************************************************
+ * Operation.
+ */
+
+static enum bverror do_op(struct bvbltparams *bvbltparams,
+			  struct gcbatch *gcbatch,
+			  int srccount,
+			  struct gcsurface *srcinfo,
+			  struct gcalpha *gca)
+{
+	enum bverror bverror = BVERR_NONE;
+	struct gcsurface *dstinfo;
+	int sw, sh, dw, dh;
+
+	GCDBG(GCZONE_BLIT, "processing source %d.\n", srcinfo->index + 1);
+
+	if (gca == NULL) {
+		GCDBG(GCZONE_BLIT,
+		      "  blending disabled.\n");
+
+		srcinfo->gca = NULL;
+		srcinfo->globalcolorenable = false;
+		srcinfo->srcglobalpremul = GCREG_SRC_GLOBAL_PREMULTIPLY_DISABLE;
+		srcinfo->srcglobalmode = GCREG_GLOBAL_ALPHA_MODE_NORMAL;
+		srcinfo->dstglobalmode = GCREG_GLOBAL_ALPHA_MODE_NORMAL;
+	} else {
+		if (srcinfo->index == 0) {
+			/* First source. */
+
+			if (srccount == 1) {
+				/* Only one source. */
+				GCDBG(GCZONE_BLIT,
+				      "  enabling blending.\n");
+
+				srcinfo->gca = gca;
+				gca->srcconfig = gca->k1;
+				gca->dstconfig = gca->k2;
+
+			} else {
+				/* Two sources. */
+				GCDBG(GCZONE_BLIT,
+				      "  disabling blending for src1.\n");
+
+				srcinfo->gca = NULL;
+			}
+
+			if (gca->globalcolorenable) {
+				srcinfo->globalcolorenable = true;
+				srcinfo->globalcolor = gca->globalcolor;
+				srcinfo->srcglobalpremul
+					= GCREG_SRC_GLOBAL_PREMULTIPLY_ALPHA;
+				srcinfo->srcglobalmode
+					= GCREG_GLOBAL_ALPHA_MODE_SCALED;
+				srcinfo->dstglobalmode
+					= GCREG_GLOBAL_ALPHA_MODE_NORMAL;
+			} else {
+				srcinfo->globalcolorenable = false;
+				srcinfo->srcglobalpremul
+					= GCREG_SRC_GLOBAL_PREMULTIPLY_DISABLE;
+				srcinfo->srcglobalmode
+					= GCREG_GLOBAL_ALPHA_MODE_NORMAL;
+				srcinfo->dstglobalmode
+					= GCREG_GLOBAL_ALPHA_MODE_NORMAL;
+			}
+		} else {
+			/* Second source. */
+			GCDBG(GCZONE_BLIT,
+				"  enabling blending.\n");
+
+			srcinfo->gca = gca;
+			gca->srcconfig = gca->k2;
+			gca->dstconfig = gca->k1;
+
+			if (gca->globalcolorenable) {
+				srcinfo->globalcolorenable = true;
+				srcinfo->globalcolor = gca->globalcolor;
+				srcinfo->srcglobalpremul
+					= GCREG_SRC_GLOBAL_PREMULTIPLY_DISABLE;
+				srcinfo->srcglobalmode
+					= GCREG_GLOBAL_ALPHA_MODE_NORMAL;
+				srcinfo->dstglobalmode
+					= GCREG_GLOBAL_ALPHA_MODE_SCALED;
+			} else {
+				srcinfo->globalcolorenable = false;
+				srcinfo->srcglobalpremul
+					= GCREG_SRC_GLOBAL_PREMULTIPLY_DISABLE;
+				srcinfo->srcglobalmode
+					= GCREG_GLOBAL_ALPHA_MODE_NORMAL;
+				srcinfo->dstglobalmode
+					= GCREG_GLOBAL_ALPHA_MODE_NORMAL;
+			}
+		}
+	}
+
+	sw = srcinfo->rect.orig.right  - srcinfo->rect.orig.left;
+	sh = srcinfo->rect.orig.bottom - srcinfo->rect.orig.top;
+
+	dw = bvbltparams->dstrect.width;
+	dh = bvbltparams->dstrect.height;
+
+	GCDBG(GCZONE_BLIT, "  srcsize %dx%d.\n", sw, sh);
+	GCDBG(GCZONE_BLIT, "  dstsize %dx%d.\n", dw, dh);
+
+	if ((sw == 0) || (sh == 0)) {
+		GCDBG(GCZONE_BLIT, "  empty source, skipping.\n");
+	} else if ((dw == 0) || (dh == 0)) {
+		GCDBG(GCZONE_BLIT, "  empty destination, skipping.\n");
+	} else if ((sw == 1) && (sh == 1) && (srcinfo->buf.desc->virtaddr)) {
+		GCDBG(GCZONE_BLIT, "  op: fill.\n");
+		bverror = do_fill(bvbltparams, gcbatch, srcinfo);
+	} else if ((sw == dw) && (sh == dh)) {
+		GCDBG(GCZONE_BLIT, "  op: bitblit.\n");
+		bverror = do_blit(bvbltparams, gcbatch, srcinfo);
+	} else {
+		GCDBG(GCZONE_BLIT, "  op: filter.\n");
+		bverror = do_filter(bvbltparams, gcbatch, srcinfo);
+	}
+
+	/* Reset dirty flags. */
+	dstinfo = &gcbatch->dstinfo;
+	dstinfo->surfdirty = false;
+	dstinfo->rectdirty = false;
+	dstinfo->cliprectdirty = false;
+	dstinfo->destrectdirty = false;
+
+	return bverror;
+}
+
+
+/*******************************************************************************
+ * Library constructor and destructor.
+ */
+
+void bv_init(void)
+{
+	struct gccontext *gccontext = get_context();
+	struct gcicaps gcicaps;
+	unsigned i, j;
+
+	GCDBG_REGISTER(bv,     ~GCZONE_BUFFER);
+	GCDBG_REGISTER(parser, GCZONE_ALL);
+	GCDBG_REGISTER(map,    GCZONE_NONE);
+	GCDBG_REGISTER(buffer, GCZONE_NONE);
+	GCDBG_REGISTER(fill,   GCZONE_ALL);
+	GCDBG_REGISTER(blit,   GCZONE_ALL);
+	GCDBG_REGISTER(filter, GCZONE_ALL);
+
+	gcbv_debug_init();
+
+	GCLOCK_INIT(&gccontext->batchlock);
+	GCLOCK_INIT(&gccontext->bufferlock);
+	GCLOCK_INIT(&gccontext->fixuplock);
+	GCLOCK_INIT(&gccontext->maplock);
+	GCLOCK_INIT(&gccontext->callbacklock);
+
+	INIT_LIST_HEAD(&gccontext->unmapvac);
+	INIT_LIST_HEAD(&gccontext->buffervac);
+	INIT_LIST_HEAD(&gccontext->fixupvac);
+	INIT_LIST_HEAD(&gccontext->batchvac);
+	INIT_LIST_HEAD(&gccontext->callbacklist);
+	INIT_LIST_HEAD(&gccontext->callbackvac);
+
+	/* Initialize the filter cache. */
+	for (i = 0; i < GC_FILTER_COUNT; i += 1)
+		for (j = 0; j < GC_TAP_COUNT; j += 1)
+			INIT_LIST_HEAD(&gccontext->filtercache[i][j].list);
+
+	/* Query hardware caps. */
+	gc_getcaps_wrapper(&gcicaps);
+	if (gcicaps.gcerror == GCERR_NONE) {
+		gccontext->gcmodel = gcicaps.gcmodel;
+		gccontext->gcrevision = gcicaps.gcrevision;
+		gccontext->gcdate = gcicaps.gcdate;
+		gccontext->gctime = gcicaps.gctime;
+
+		gccontext->gccaps.l2cachefor420
+			= (gcicaps.gcfeatures2.reg.l2cachefor420 != 0);
+
+		if (gcicaps.gcfeatures3.reg.newfeatures0) {
+			gccontext->gccaps.maxsource = 8;
+			gccontext->gccaps.strictalign = false;
+		} else {
+			gccontext->gccaps.maxsource = 4;
+			gccontext->gccaps.strictalign = true;
+		}
+
+		gccontext->gccaps.swizzlefixed
+			= (gcicaps.gcfeatures3.reg.deenhancements1 != 0);
+
+		GCDBG(GCZONE_INIT, "chip model: %X\n",
+		      gccontext->gcmodel);
+		GCDBG(GCZONE_INIT, "chip revision: %X\n",
+		      gccontext->gcrevision);
+		GCDBG(GCZONE_INIT, "chip date: %X\n",
+		      gccontext->gcdate);
+		GCDBG(GCZONE_INIT, "chip time: %X\n",
+		      gccontext->gctime);
+		GCDBG(GCZONE_INIT, "max source: %d\n",
+		      gccontext->gccaps.maxsource);
+		GCDBG(GCZONE_INIT, "strict alignment: %d\n",
+		      gccontext->gccaps.strictalign);
+		GCDBG(GCZONE_INIT, "swizzle fixed: %d\n",
+		      gccontext->gccaps.swizzlefixed);
+	} else {
+		GCERR("failed to get chip caps.\n");
+		gccontext->gccaps.l2cachefor420 = false;
+		gccontext->gccaps.maxsource = 4;
+		gccontext->gccaps.strictalign = true;
+		gccontext->gccaps.swizzlefixed = false;
+	}
+}
+
+void bv_exit(void)
+{
+	struct gccontext *gccontext = get_context();
+	struct bvbuffmap *bvbuffmap;
+	struct list_head *head;
+	struct gcschedunmap *gcschedunmap;
+	struct gcbuffer *gcbuffer;
+	struct gcfixup *gcfixup;
+	struct gcbatch *gcbatch;
+	struct gccallbackinfo *gccallbackinfo;
+
+	while (gccontext->buffmapvac != NULL) {
+		bvbuffmap = gccontext->buffmapvac;
+		gccontext->buffmapvac = bvbuffmap->nextmap;
+		gcfree(bvbuffmap);
+	}
+
+	while (!list_empty(&gccontext->unmapvac)) {
+		head = gccontext->unmapvac.next;
+		gcschedunmap = list_entry(head, struct gcschedunmap, link);
+		list_del(head);
+		gcfree(gcschedunmap);
+	}
+
+	while (!list_empty(&gccontext->buffervac)) {
+		head = gccontext->buffervac.next;
+		gcbuffer = list_entry(head, struct gcbuffer, link);
+		list_del(head);
+		gcfree(gcbuffer);
+	}
+
+	while (!list_empty(&gccontext->fixupvac)) {
+		head = gccontext->fixupvac.next;
+		gcfixup = list_entry(head, struct gcfixup, link);
+		list_del(head);
+		gcfree(gcfixup);
+	}
+
+	while (!list_empty(&gccontext->batchvac)) {
+		head = gccontext->batchvac.next;
+		gcbatch = list_entry(head, struct gcbatch, link);
+		list_del(head);
+		gcfree(gcbatch);
+	}
+
+	while (!list_empty(&gccontext->callbacklist)) {
+		head = gccontext->callbacklist.next;
+		list_move(head, &gccontext->callbackvac);
+	}
+
+	while (!list_empty(&gccontext->callbackvac)) {
+		head = gccontext->callbackvac.next;
+		gccallbackinfo = list_entry(head, struct gccallbackinfo, link);
+		list_del(head);
+		gcfree(gccallbackinfo);
+	}
+
+	free_temp(false);
+
+	gcbv_debug_shutdown();
+}
+
+
+/*******************************************************************************
+ * Library API.
+ */
+
+enum bverror bv_map(struct bvbuffdesc *bvbuffdesc)
+{
+	enum bverror bverror;
+	struct bvbuffmap *bvbuffmap;
+
+	GCENTERARG(GCZONE_MAPPING, "bvbuffdesc = 0x%08X\n",
+		   (unsigned int) bvbuffdesc);
+
+	if (bvbuffdesc == NULL) {
+		BVSETERROR(BVERR_BUFFERDESC, "bvbuffdesc is NULL");
+		goto exit;
+	}
+
+	if (bvbuffdesc->structsize < STRUCTSIZE(bvbuffdesc, map)) {
+		BVSETERROR(BVERR_BUFFERDESC_VERS, "argument has invalid size");
+		goto exit;
+	}
+
+	bverror = do_map(bvbuffdesc, NULL, &bvbuffmap);
+
+exit:
+	GCEXITARG(GCZONE_MAPPING, "bv%s = %d\n",
+		  (bverror == BVERR_NONE) ? "result" : "error", bverror);
+	return bverror;
+}
+
+enum bverror bv_unmap(struct bvbuffdesc *bvbuffdesc)
+{
+	enum bverror bverror = BVERR_NONE;
+	enum bverror otherbverror = BVERR_NONE;
+	struct gccontext *gccontext = get_context();
+	struct bvbuffmap *prev = NULL;
+	struct bvbuffmap *bvbuffmap;
+	struct bvbuffmapinfo *bvbuffmapinfo;
+	struct gcimap gcimap;
+
+	GCENTERARG(GCZONE_MAPPING, "bvbuffdesc = 0x%08X\n",
+		   (unsigned int) bvbuffdesc);
+
+	/* Lock access to the mapping list. */
+	GCLOCK(&gccontext->maplock);
+
+	if (bvbuffdesc == NULL) {
+		BVSETERROR(BVERR_BUFFERDESC, "bvbuffdesc is NULL");
+		goto exit;
+	}
+
+	if (bvbuffdesc->structsize < STRUCTSIZE(bvbuffdesc, map)) {
+		BVSETERROR(BVERR_BUFFERDESC_VERS, "argument has invalid size");
+		goto exit;
+	}
+
+	/* Is the buffer mapped? */
+	bvbuffmap = bvbuffdesc->map;
+	if (bvbuffmap == NULL) {
+		GCDBG(GCZONE_MAPPING, "buffer isn't mapped.\n");
+		goto exit;
+	}
+
+	/* Try to find our mapping. */
+	while (bvbuffmap != NULL) {
+		if (bvbuffmap->bv_unmap == bv_unmap)
+			break;
+		prev = bvbuffmap;
+		bvbuffmap = bvbuffmap->nextmap;
+	}
+
+	/* Are there other implementations? */
+	if ((prev != NULL) || (bvbuffmap->nextmap != NULL)) {
+		GCDBG(GCZONE_MAPPING,
+		      "have mappings from other implementations.\n");
+
+		/* Was our mapping found? */
+		if (bvbuffmap == NULL) {
+			GCDBG(GCZONE_MAPPING,
+			      "no mapping from our implementation.\n");
+
+			/* No, call other implementations. */
+			bverror = bvbuffdesc->map->bv_unmap(bvbuffdesc);
+			goto exit;
+		}
+
+		if (bvbuffmap->structsize
+				< STRUCTSIZE(bvbuffmap, nextmap)) {
+			BVSETERROR(BVERR_BUFFERDESC_VERS,
+				   "unsupported bvbuffdesc version");
+			goto exit;
+		}
+
+		/* Remove our mapping. */
+		if (prev == NULL)
+			bvbuffdesc->map = bvbuffmap->nextmap;
+		else
+			prev->nextmap = bvbuffmap->nextmap;
+
+		/* Call other implementation. */
+		otherbverror = bvbuffdesc->map->bv_unmap(bvbuffdesc);
+
+		/* Add our mapping back. */
+		bvbuffmap->nextmap = bvbuffdesc->map;
+		bvbuffdesc->map = bvbuffmap;
+		prev = NULL;
+	} else {
+		GCDBG(GCZONE_MAPPING,
+		      "no mappings from other implementations.\n");
+	}
+
+	/* Get the info structure. */
+	bvbuffmapinfo = (struct bvbuffmapinfo *) bvbuffmap->handle;
+
+	GCDBG(GCZONE_MAPPING, "bvbuffmap = 0x%08X\n", (unsigned int) bvbuffmap);
+	GCDBG(GCZONE_MAPPING, "handle = 0x%08X\n", bvbuffmapinfo->handle);
+
+	/* Explicit unmapping. */
+	if (bvbuffmapinfo->usermap == 0)
+		GCERR("explicit count is already zero.\n");
+	bvbuffmapinfo->usermap = 0;
+
+	GCDBG(GCZONE_MAPPING, "explicit count = %d\n",
+		bvbuffmapinfo->usermap);
+	GCDBG(GCZONE_MAPPING, "implicit count = %d\n",
+		bvbuffmapinfo->automap);
+
+	/* Do we have implicit mappings? */
+	if (bvbuffmapinfo->automap > 0) {
+		GCDBG(GCZONE_MAPPING, "have implicit unmappings.\n");
+		goto exit;
+	}
+
+	/* Unmap the buffer. */
+	memset(&gcimap, 0, sizeof(gcimap));
+	gcimap.handle = bvbuffmapinfo->handle;
+	gc_unmap_wrapper(&gcimap);
+	if (gcimap.gcerror != GCERR_NONE) {
+		BVSETERROR(BVERR_OOM, "unable to free gccore memory");
+		goto exit;
+	}
+
+	/* Remove from the buffer descriptor list. */
+	if (prev == NULL)
+		bvbuffdesc->map = bvbuffmap->nextmap;
+	else
+		prev->nextmap = bvbuffmap->nextmap;
+
+	/* Invalidate the record. */
+	bvbuffmap->structsize = 0;
+
+	/* Add to the vacant list. */
+	bvbuffmap->nextmap = gccontext->buffmapvac;
+	gccontext->buffmapvac = bvbuffmap;
+
+exit:
+	/* Unlock access to the mapping list. */
+	GCUNLOCK(&gccontext->maplock);
+
+	GCEXITARG(GCZONE_MAPPING, "bv%s = %d\n",
+		  (bverror == BVERR_NONE) ? "result" : "error", bverror);
+	return bverror;
+}
+
+enum bverror bv_blt(struct bvbltparams *bvbltparams)
+{
+	enum bverror bverror = BVERR_NONE;
+	struct gccontext *gccontext = get_context();
+	struct gcalpha *gca = NULL;
+	struct gcalpha _gca;
+	unsigned int op, type, blend, format;
+	unsigned int batchexec = 0;
+	bool nop = false;
+	struct gcbatch *gcbatch;
+	struct gcsurface *dstinfo;
+	struct bvrect *dstrect;
+	bool dstonly, src1used, src2used, maskused;
+	struct gcsurface srcinfo[2];
+	unsigned short rop;
+	struct gcicommit gcicommit;
+	int i, srccount, res;
+
+	GCENTERARG(GCZONE_BLIT, "bvbltparams = 0x%08X\n",
+		   (unsigned int) bvbltparams);
+
+	/* Verify blt parameters structure. */
+	if (bvbltparams == NULL) {
+		BVSETERROR(BVERR_BLTPARAMS_VERS, "bvbltparams is NULL");
+		goto exit;
+	}
+
+	if (bvbltparams->structsize < STRUCTSIZE(bvbltparams, callbackdata)) {
+		BVSETERROR(BVERR_BLTPARAMS_VERS, "argument has invalid size");
+		goto exit;
+	}
+
+	/* Reset the error message. */
+	bvbltparams->errdesc = NULL;
+
+	/* Verify the destination parameters structure. */
+	res = verify_surface(0, (union bvinbuff *) &bvbltparams->dstdesc,
+				bvbltparams->dstgeom);
+	if (res != -1) {
+		BVSETBLTSURFERROR(res, g_destsurferr);
+		goto exit;
+	}
+
+	/* Extract the operation flags. */
+	op = (bvbltparams->flags & BVFLAG_OP_MASK) >> BVFLAG_OP_SHIFT;
+	type = (bvbltparams->flags & BVFLAG_BATCH_MASK) >> BVFLAG_BATCH_SHIFT;
+	GCDBG(GCZONE_BLIT, "op = %d\n", op);
+	GCDBG(GCZONE_BLIT, "type = %d\n", type);
+
+	switch (type) {
+	case (BVFLAG_BATCH_NONE >> BVFLAG_BATCH_SHIFT):
+		bverror = allocate_batch(bvbltparams, &gcbatch);
+		if (bverror != BVERR_NONE) {
+			bvbltparams->errdesc = gccontext->bverrorstr;
+			goto exit;
+		}
+
+		batchexec = 1;
+		gcbatch->batchflags = 0x7FFFFFFF;
+
+		GCDBG(GCZONE_BATCH, "BVFLAG_BATCH_NONE(0x%08X)\n",
+		      (unsigned int) gcbatch);
+		break;
+
+	case (BVFLAG_BATCH_BEGIN >> BVFLAG_BATCH_SHIFT):
+		bverror = allocate_batch(bvbltparams, &gcbatch);
+		if (bverror != BVERR_NONE) {
+			bvbltparams->errdesc = gccontext->bverrorstr;
+			goto exit;
+		}
+
+		bvbltparams->batch = (struct bvbatch *) gcbatch;
+
+		batchexec = 0;
+		bvbltparams->batchflags =
+		gcbatch->batchflags = 0x7FFFFFFF;
+
+		GCDBG(GCZONE_BATCH, "BVFLAG_BATCH_BEGIN(0x%08X)\n",
+		      (unsigned int) gcbatch);
+		break;
+
+	case (BVFLAG_BATCH_CONTINUE >> BVFLAG_BATCH_SHIFT):
+		gcbatch = (struct gcbatch *) bvbltparams->batch;
+		if (gcbatch == NULL) {
+			BVSETBLTERROR(BVERR_BATCH, "batch is not initialized");
+			goto exit;
+		}
+
+		if (gcbatch->structsize < STRUCTSIZE(gcbatch, unmap)) {
+			BVSETBLTERROR(BVERR_BATCH, "invalid batch");
+			goto exit;
+		}
+
+		batchexec = 0;
+		gcbatch->batchflags = bvbltparams->batchflags;
+
+		GCDBG(GCZONE_BATCH, "BVFLAG_BATCH_CONTINUE(0x%08X)\n",
+		      (unsigned int) gcbatch);
+		break;
+
+	case (BVFLAG_BATCH_END >> BVFLAG_BATCH_SHIFT):
+		gcbatch = (struct gcbatch *) bvbltparams->batch;
+		if (gcbatch == NULL) {
+			BVSETBLTERROR(BVERR_BATCH, "batch is not initialized");
+			goto exit;
+		}
+
+		if (gcbatch->structsize < STRUCTSIZE(gcbatch, unmap)) {
+			BVSETBLTERROR(BVERR_BATCH, "invalid batch");
+			goto exit;
+		}
+
+		batchexec = 1;
+		nop = (bvbltparams->batchflags & BVBATCH_ENDNOP) != 0;
+		gcbatch->batchflags = bvbltparams->batchflags;
+
+		GCDBG(GCZONE_BATCH, "BVFLAG_BATCH_END(0x%08X)\n",
+		      (unsigned int) gcbatch);
+		break;
+
+	default:
+		BVSETBLTERROR(BVERR_BATCH, "unrecognized batch type");
+		goto exit;
+	}
+
+	GCDBG(GCZONE_BATCH, "batchflags=0x%08X\n",
+		(unsigned int) gcbatch->batchflags);
+
+	if (!nop) {
+		/* Get a shortcut to the destination rectangle. */
+		dstrect = &bvbltparams->dstrect;
+
+		/* Verify the batch change flags. */
+		GCVERIFYBATCH(gcbatch->batchflags >> 12,
+			      &gcbatch->prevdstrect, dstrect);
+
+		switch (op) {
+		case (BVFLAG_ROP >> BVFLAG_OP_SHIFT):
+			GCDBG(GCZONE_BLIT, "BVFLAG_ROP\n");
+
+			rop = bvbltparams->op.rop;
+			dstonly = (rop == 0x0000) | (rop == 0x5555)
+				| (rop == 0xAAAA) | (rop == 0xFFFF);
+			src1used = ((((rop & 0xCCCC)  >> 2)
+				 ^    (rop & 0x3333)) != 0);
+			src2used = ((((rop & 0xF0F0)  >> 4)
+				 ^    (rop & 0x0F0F)) != 0);
+			maskused = ((((rop & 0xFF00)  >> 8)
+				 ^    (rop & 0x00FF)) != 0);
+			break;
+
+		case (BVFLAG_BLEND >> BVFLAG_OP_SHIFT):
+			GCDBG(GCZONE_BLIT, "BVFLAG_BLEND\n");
+
+			blend = bvbltparams->op.blend;
+			format = blend & BVBLENDDEF_FORMAT_MASK;
+			maskused = (blend & BVBLENDDEF_REMOTE) != 0;
+			rop = 0xCCCC;
+
+			GCDBG(GCZONE_BLIT, "blend = 0x%08X (%s)\n",
+			      blend, gc_bvblend_name(blend));
+
+			if (format != BVBLENDDEF_FORMAT_CLASSIC) {
+				BVSETBLTERROR(BVERR_BLEND,
+					      "unrecognized blend format");
+				goto exit;
+			}
+
+			if (blend == BVBLEND_CLEAR) {
+				dstonly = true;
+				src1used = false;
+				src2used = false;
+			} else {
+				bverror = parse_blend(bvbltparams, blend,
+						      &_gca);
+				if (bverror != BVERR_NONE)
+					goto exit;
+
+				gca = &_gca;
+
+				dstonly = false;
+				src1used = gca->src1used;
+				src2used = gca->src2used;
+			}
+			break;
+
+		case (BVFLAG_FILTER >> BVFLAG_OP_SHIFT):
+			GCDBG(GCZONE_BLIT, "BVFLAG_FILTER\n");
+			BVSETBLTERROR(BVERR_OP,
+				      "filter operation not supported");
+			goto exit;
+
+		default:
+			BVSETBLTERROR(BVERR_OP, "unrecognized operation");
+			goto exit;
+		}
+
+		/* Reset the number of sources. */
+		srccount = 0;
+
+		/* Determine what's changed in the destination. */
+		dstinfo = &gcbatch->dstinfo;
+		dstinfo->surfdirty
+			= ((gcbatch->batchflags & BVBATCH_DST) != 0);
+		dstinfo->cliprectdirty
+			= ((gcbatch->batchflags & BVBATCH_CLIPRECT) != 0);
+		dstinfo->destrectdirty
+			= ((gcbatch->batchflags & BVBATCH_DESTRECT) != 0);
+		dstinfo->rectdirty
+			= dstinfo->cliprectdirty || dstinfo->destrectdirty;
+
+		/* Verify the src1 parameters structure. */
+		if (src1used) {
+			GCDBG(GCZONE_SRC, "source #1: used\n");
+			res = verify_surface(
+				bvbltparams->flags & BVBATCH_TILE_SRC1,
+				&bvbltparams->src1, bvbltparams->src1geom);
+			if (res != -1) {
+				BVSETBLTSURFERROR(res, g_src1surferr);
+				goto exit;
+			}
+
+			/* Verify the batch change flags. */
+			GCVERIFYBATCH(gcbatch->batchflags >> 14,
+				      &gcbatch->prevsrc1rect,
+				      &bvbltparams->src1rect);
+
+			/* Same as the destination? */
+			if (same_phys_area(bvbltparams->src1.desc,
+					   &bvbltparams->src1rect,
+					   bvbltparams->dstdesc,
+					   dstrect)) {
+				GCDBG(GCZONE_BLIT,
+				      "  src1 same as destination\n");
+			} else {
+				bverror = parse_source(bvbltparams,
+						       gcbatch,
+						       &srcinfo[srccount],
+						       0, rop);
+				if (bverror != BVERR_NONE)
+					goto exit;
+
+				srccount += 1;
+			}
+		}
+
+		/* Verify the src2 parameters structure. */
+		if (src2used) {
+			GCDBG(GCZONE_SRC, "source #2: used\n");
+			res = verify_surface(
+				bvbltparams->flags & BVBATCH_TILE_SRC2,
+				&bvbltparams->src2, bvbltparams->src2geom);
+			if (res != -1) {
+				BVSETBLTSURFERROR(res, g_src2surferr);
+				goto exit;
+			}
+
+			/* Verify the batch change flags. */
+			GCVERIFYBATCH(gcbatch->batchflags >> 16,
+				      &gcbatch->prevsrc2rect,
+				      &bvbltparams->src2rect);
+
+			/* Same as the destination? */
+			if (same_phys_area(bvbltparams->src2.desc,
+					   &bvbltparams->src2rect,
+					   bvbltparams->dstdesc,
+					   dstrect)) {
+				GCDBG(GCZONE_BLIT,
+				      "  src2 same as destination\n");
+			} else {
+				bverror = parse_source(bvbltparams,
+						       gcbatch,
+						       &srcinfo[srccount],
+						       1, rop);
+				if (bverror != BVERR_NONE)
+					goto exit;
+
+				srccount += 1;
+			}
+		}
+
+		/* Verify the mask parameters structure. */
+		if (maskused) {
+			GCDBG(GCZONE_MASK, "mask: used\n");
+			res = verify_surface(
+				bvbltparams->flags & BVBATCH_TILE_MASK,
+				&bvbltparams->mask, bvbltparams->maskgeom);
+			if (res != -1) {
+				BVSETBLTSURFERROR(res, g_masksurferr);
+				goto exit;
+			}
+
+			/* Verify the batch change flags. */
+			GCVERIFYBATCH(gcbatch->batchflags >> 18,
+				      &gcbatch->prevmaskrect,
+				      &bvbltparams->maskrect);
+
+			BVSETBLTERROR(BVERR_OP,
+				      "operation with mask not supported");
+			goto exit;
+		}
+
+		/* Destination only? */
+		if (dstonly) {
+			static unsigned int pixel[8];
+			static struct bvbuffdesc dummysrcdesc;
+			static struct gcsurface dummysrcinfo;
+			static bool dummyinit;
+
+			GCDBG(GCZONE_BLIT, "target only operation.\n");
+
+			if (!dummyinit) {
+				GCDBG(GCZONE_BLIT,
+				      "initializing dummy source.\n");
+
+				dummysrcdesc.structsize
+					= sizeof(struct bvbuffdesc);
+				dummysrcdesc.virtaddr = pixel;
+				dummysrcdesc.length = sizeof(pixel);
+
+				dummysrcinfo.buf.desc = &dummysrcdesc;
+				dummysrcinfo.width = 1;
+				dummysrcinfo.height = 1;
+				dummysrcinfo.stride1 = sizeof(pixel);
+				dummysrcinfo.rect.orig.right = 1;
+				dummysrcinfo.rect.orig.bottom = 1;
+
+				parse_format(bvbltparams, OCDFMT_RGBA24,
+					     &dummysrcinfo.format);
+
+				dummyinit = true;
+			}
+
+			dummysrcinfo.rop = rop;
+			bverror = do_op(bvbltparams, gcbatch,
+					1, &dummysrcinfo, NULL);
+			if (bverror != BVERR_NONE)
+				goto exit;
+		} else {
+			GCDBG(GCZONE_BLIT, "srccount = %d\n", srccount);
+
+			if (srccount == 0) {
+				BVSETBLTERROR(BVERR_OP,
+					      "operation not supported");
+				goto exit;
+			}
+
+			for (i = 0; i < srccount; i += 1) {
+				bverror = do_op(bvbltparams, gcbatch,
+						srccount, &srcinfo[i], gca);
+				if (bverror != BVERR_NONE)
+					goto exit;
+			}
+		}
+	}
+
+	if (batchexec) {
+		struct gcmoflush *flush;
+
+		GCDBG(GCZONE_BLIT, "preparing to submit the batch.\n");
+
+		/* Finalize the current operation. */
+		bverror = gcbatch->batchend(bvbltparams, gcbatch);
+		if (bverror != BVERR_NONE)
+			goto exit;
+
+		/* Add PE flush. */
+		GCDBG(GCZONE_BLIT, "appending the flush.\n");
+		bverror = claim_buffer(bvbltparams, gcbatch,
+				       sizeof(struct gcmoflush),
+				       (void **) &flush);
+		if (bverror != BVERR_NONE)
+			goto exit;
+
+		flush->flush_ldst = gcmoflush_flush_ldst;
+		flush->flush.reg = gcregflush_pe2D;
+
+		/* Process asynchronous operation. */
+		if ((bvbltparams->flags & BVFLAG_ASYNC) == 0) {
+			GCDBG(GCZONE_BLIT, "synchronous batch.\n");
+			gcicommit.callback = NULL;
+			gcicommit.callbackparam = NULL;
+			gcicommit.asynchronous = false;
+		} else {
+			struct gccallbackinfo *gccallbackinfo;
+
+			GCDBG(GCZONE_BLIT, "asynchronous batch (0x%08X):\n",
+			      bvbltparams->flags);
+
+			if (bvbltparams->callbackfn == NULL) {
+				GCDBG(GCZONE_BLIT, "no callback given.\n");
+				gcicommit.callback = NULL;
+				gcicommit.callbackparam = NULL;
+			} else {
+				bverror = get_callbackinfo(&gccallbackinfo);
+				if (bverror != BVERR_NONE) {
+					BVSETBLTERROR(BVERR_OOM,
+						      "callback allocation "
+						      "failed");
+					goto exit;
+				}
+
+				gccallbackinfo->info.callback.fn
+					= bvbltparams->callbackfn;
+				gccallbackinfo->info.callback.data
+					= bvbltparams->callbackdata;
+
+				gcicommit.callback = callbackbltsville;
+				gcicommit.callbackparam = gccallbackinfo;
+
+				GCDBG(GCZONE_BLIT,
+				      "gcbv_callback = 0x%08X\n",
+				      (unsigned int) gcicommit.callback);
+				GCDBG(GCZONE_BLIT,
+				      "gcbv_param    = 0x%08X\n",
+				      (unsigned int) gcicommit.callbackparam);
+				GCDBG(GCZONE_BLIT,
+				      "bltsville_callback = 0x%08X\n",
+				      (unsigned int)
+				      gccallbackinfo->info.callback.fn);
+				GCDBG(GCZONE_BLIT,
+				      "bltsville_param    = 0x%08X\n",
+				      (unsigned int)
+				      gccallbackinfo->info.callback.data);
+			}
+
+			gcicommit.asynchronous = true;
+		}
+
+		/* Process scheduled unmappings. */
+		do_unmap_implicit(gcbatch);
+
+		INIT_LIST_HEAD(&gcicommit.unmap);
+		list_splice_init(&gcbatch->unmap, &gcicommit.unmap);
+
+		/* Pass the batch for execution. */
+		GCDUMPBATCH(gcbatch);
+
+		gcicommit.gcerror = GCERR_NONE;
+		gcicommit.entrypipe = GCPIPE_2D;
+		gcicommit.exitpipe = GCPIPE_2D;
+
+		INIT_LIST_HEAD(&gcicommit.buffer);
+		list_splice_init(&gcbatch->buffer, &gcicommit.buffer);
+
+		GCDBG(GCZONE_BLIT, "submitting the batch.\n");
+		gc_commit_wrapper(&gcicommit);
+
+		/* Move the lists back to the batch. */
+		list_splice_init(&gcicommit.buffer, &gcbatch->buffer);
+		list_splice_init(&gcicommit.unmap, &gcbatch->unmap);
+
+		/* Error? */
+		if (gcicommit.gcerror != GCERR_NONE) {
+			switch (gcicommit.gcerror) {
+			case GCERR_OODM:
+			case GCERR_CTX_ALLOC:
+				BVSETBLTERROR(BVERR_OOM,
+					      "unable to allocate gccore "
+					      "memory");
+				goto exit;
+			default:
+				BVSETBLTERROR(BVERR_RSRC,
+					      "gccore error");
+
+				goto exit;
+			}
+		}
+
+		GCDBG(GCZONE_BLIT, "batch is submitted.\n");
+	}
+
+exit:
+	if ((gcbatch != NULL) && batchexec) {
+		free_batch(gcbatch);
+		bvbltparams->batch = NULL;
+	}
+
+	GCEXITARG(GCZONE_BLIT, "bv%s = %d\n",
+		  (bverror == BVERR_NONE) ? "result" : "error", bverror);
+	return bverror;
+}
+
+enum bverror bv_cache(struct bvcopparams *copparams)
+{
+	enum bverror bverror = BVERR_NONE;
+	unsigned int bytespp = 0; /* bytes per pixel */
+	unsigned long vert_offset, horiz_offset;
+	unsigned int true_width, true_height;
+
+	struct c2dmrgn rgn[3];
+	int container_size = 0;
+
+	unsigned long subsample;
+	unsigned long vendor;
+	unsigned long layout;
+	unsigned long size;
+	unsigned long container;
+
+	subsample = copparams->geom->format & OCDFMTDEF_SUBSAMPLE_MASK;
+	vendor = copparams->geom->format & OCDFMTDEF_VENDOR_MASK;
+	layout = copparams->geom->format & OCDFMTDEF_LAYOUT_MASK;
+	size = copparams->geom->format & OCDFMTDEF_COMPONENTSIZEMINUS1_MASK;
+	container = copparams->geom->format & OCDFMTDEF_CONTAINER_MASK;
+
+	if (vendor != OCDFMTDEF_VENDOR_ALL) {
+		bverror = BVERR_FORMAT;
+		goto exit;
+	}
+
+	if (copparams->geom->orientation % 180 != 0) {
+		true_width = copparams->rect->height;
+		true_height = copparams->rect->width;
+	} else {
+		true_width = copparams->rect->width;
+		true_height = copparams->rect->height;
+	}
+
+	switch (container) {
+	case OCDFMTDEF_CONTAINER_8BIT:
+		container_size = 8;
+		break;
+
+	case OCDFMTDEF_CONTAINER_16BIT:
+		container_size = 16;
+		break;
+
+	case OCDFMTDEF_CONTAINER_24BIT:
+		container_size = 24;
+		break;
+
+	case OCDFMTDEF_CONTAINER_32BIT:
+		container_size = 32;
+		break;
+
+	case OCDFMTDEF_CONTAINER_48BIT:
+		container_size = 48;
+		break;
+
+	case OCDFMTDEF_CONTAINER_64BIT:
+		container_size = 64;
+		break;
+	}
+
+	switch (layout) {
+	case OCDFMTDEF_PACKED:
+		switch (subsample) {
+		case OCDFMTDEF_SUBSAMPLE_NONE:
+			if (size >= 8) {
+				bytespp = container_size / 8;
+			} else {
+				GCERR("format not supported.\n");
+				bverror = BVERR_FORMAT;
+				goto exit;
+			}
+			break;
+
+		case OCDFMTDEF_SUBSAMPLE_422_YCbCr:
+			bytespp = (container_size / 2) / 8;
+			break;
+
+		default:
+			bverror = BVERR_FORMAT;
+			goto exit;
+		}
+
+		rgn[0].span = true_width * bytespp;
+		rgn[0].lines = true_height;
+		rgn[0].stride = copparams->geom->virtstride;
+		horiz_offset = copparams->rect->left * bytespp;
+		vert_offset = copparams->rect->top;
+
+		rgn[0].start = (void *) ((unsigned long)
+				copparams->desc->virtaddr +
+				vert_offset * rgn[0].stride +
+				horiz_offset);
+
+		gcbvcacheop(1, rgn, copparams->cacheop);
+		break;
+
+	case OCDFMTDEF_2_PLANE_YCbCr:
+		/* 1 byte per pixel */
+		rgn[0].span = true_width;
+		rgn[0].lines = true_height;
+		rgn[0].stride = copparams->geom->virtstride;
+		rgn[0].start = (void *)
+			((unsigned long) copparams->desc->virtaddr +
+			 copparams->rect->top * rgn[0].stride +
+			 copparams->rect->left);
+
+		rgn[1].span = true_width;
+		rgn[1].lines = true_height / 2;
+		rgn[1].stride = copparams->geom->virtstride;
+		rgn[1].start = rgn[0].start +
+			copparams->geom->height * rgn[0].stride;
+
+		GCDBG(GCZONE_CACHE,
+		      "virtaddr %p start[0] 0x%08x start[1] 0x%08x\n",
+		      copparams->desc->virtaddr, rgn[0].start, rgn[1].start);
+
+		gcbvcacheop(2, rgn, copparams->cacheop);
+		break;
+
+	default:
+		GCERR("format 0x%x (%d) not supported.\n",
+		      copparams->geom->format, copparams->geom->format);
+		bverror = BVERR_FORMAT;
+		break;
+	}
+
+exit:
+	if (bverror != BVERR_NONE)
+		GCERR("bverror = %d\n", bverror);
+
+	return bverror;
+}
diff --git a/drivers/misc/gcx/gcbv/gcbv.h b/drivers/misc/gcx/gcbv/gcbv.h
new file mode 100644
index 0000000..7e5696a
--- /dev/null
+++ b/drivers/misc/gcx/gcbv/gcbv.h
@@ -0,0 +1,615 @@
+/*
+ * This file is provided under a dual BSD/GPLv2 license.  When using or
+ * redistributing this file, you may do so under either license.
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * Copyright(c) 2012 Vivante Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * BSD LICENSE
+ *
+ * Copyright(c) 2012 Vivante Corporation. 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 Vivante Corporation 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 AND FITNESS FOR A PARTICULAR PURPOSE
+ * 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 GCBV_H
+#define GCBV_H
+
+#include "gcmain.h"
+
+/*******************************************************************************
+ * Miscellaneous defines and macros.
+ */
+
+#define GC_MAX_BASE_ALIGN 64
+
+#define GCBV_BATCH_FINALIZE_SRCCOUNT       (1 << 0)
+#define GCBV_BATCH_FINALIZE_MULTISRC       (1 << 1)
+#define GCBV_BATCH_FINALIZE_ALIGN          (1 << 2)
+#define GCBV_BATCH_FINALIZE_FLAGS_DST      (1 << 3)
+#define GCBV_BATCH_FINALIZE_FLAGS_DESTRECT (1 << 4)
+#define GCBV_BATCH_FINALIZE_FLAGS_CLIPRECT (1 << 5)
+#define GCBV_BATCH_FINALIZE_OPERATION      (1 << 6)
+
+#if !defined(BVBATCH_DESTRECT)
+#define BVBATCH_DESTRECT (BVBATCH_DSTRECT_ORIGIN | BVBATCH_DSTRECT_SIZE)
+#endif
+
+#if !defined(BVBATCH_SRC1RECT)
+#define BVBATCH_SRC1RECT (BVBATCH_SRC1RECT_ORIGIN | BVBATCH_SRC1RECT_SIZE)
+#endif
+
+#if !defined(BVBATCH_SRC2RECT)
+#define BVBATCH_SRC2RECT (BVBATCH_SRC2RECT_ORIGIN | BVBATCH_SRC2RECT_SIZE)
+#endif
+
+#define STRUCTSIZE(structptr, lastmember) \
+( \
+	(size_t) &structptr->lastmember + \
+	sizeof(structptr->lastmember) - \
+	(size_t) structptr \
+)
+
+#define GET_MAP_HANDLE(map) \
+( \
+	((struct bvbuffmapinfo *) map->handle)->handle \
+)
+
+#define GC_CLIP_RESET_LEFT	((unsigned short) 0)
+#define GC_CLIP_RESET_TOP	((unsigned short) 0)
+#define GC_CLIP_RESET_RIGHT	((unsigned short) ((1 << 15) - 1))
+#define GC_CLIP_RESET_BOTTOM	((unsigned short) ((1 << 15) - 1))
+
+#define BVSETERROR(error, message, ...) \
+do { \
+	struct gccontext *tmpcontext = get_context(); \
+	snprintf(tmpcontext->bverrorstr, sizeof(tmpcontext->bverrorstr), \
+		 message, ##__VA_ARGS__); \
+	GCDUMPSTRING("%s(%d): [ERROR] %s\n", __func__, __LINE__, \
+		     tmpcontext->bverrorstr); \
+	bverror = error; \
+} while (0)
+
+#define BVSETBLTERROR(error, message, ...) \
+do { \
+	struct gccontext *tmpcontext = get_context(); \
+	snprintf(tmpcontext->bverrorstr, sizeof(tmpcontext->bverrorstr), \
+		 message, ##__VA_ARGS__); \
+	GCDUMPSTRING("%s(%d): [ERROR] %s\n", __func__, __LINE__, \
+		     tmpcontext->bverrorstr); \
+	bvbltparams->errdesc = tmpcontext->bverrorstr; \
+	bverror = error; \
+} while (0)
+
+#define GCPRINT_RECT(zone, name, rect) \
+{ \
+	GCDBG(zone, \
+	      name " = (%d,%d)-(%d,%d), %dx%d\n", \
+	      (rect)->left, (rect)->top, \
+	      (rect)->right, (rect)->bottom, \
+	      (rect)->right - (rect)->left, \
+	      (rect)->bottom - (rect)->top); \
+}
+
+
+/*******************************************************************************
+ * Kernel table definitions.
+ */
+
+#define GC_TAP_COUNT		9
+#define GC_PHASE_BITS		5
+#define GC_PHASE_MAX_COUNT	(1 << GC_PHASE_BITS)
+#define GC_PHASE_LOAD_COUNT	(GC_PHASE_MAX_COUNT / 2 + 1)
+#define GC_COEFFICIENT_COUNT	(GC_PHASE_LOAD_COUNT * GC_TAP_COUNT)
+#define GC_FILTER_CACHE_MAX	10
+
+enum gcfiltertype {
+	GC_FILTER_SYNC,
+	GC_FILTER_BLUR,
+
+	/* Number of supported filter types. */
+	GC_FILTER_COUNT
+};
+
+struct gcfilterkernel {
+	enum gcfiltertype type;
+	unsigned int kernelsize;
+	unsigned int srcsize;
+	unsigned int dstsize;
+	unsigned int scalefactor;
+	short kernelarray[GC_COEFFICIENT_COUNT];
+	struct list_head link;
+};
+
+struct gcfiltercache {
+	unsigned int count;
+	struct list_head list;			/* gcfilterkernel */
+};
+
+
+/*******************************************************************************
+ * Global data structure.
+ */
+
+struct gccaps {
+	bool l2cachefor420;
+	unsigned int maxsource;
+	bool strictalign;
+	bool swizzlefixed;
+};
+
+struct gccontext {
+	/* Last generated error message. */
+	char bverrorstr[128];
+
+	/* Capabilities and characteristics. */
+	unsigned int gcmodel;
+	unsigned int gcrevision;
+	unsigned int gcdate;
+	unsigned int gctime;
+	struct gccaps gccaps;
+
+	/* Dynamically allocated structure cache. */
+	struct bvbuffmap *buffmapvac;		/* bvbuffmap */
+	struct list_head unmapvac;		/* gcschedunmap */
+	struct list_head buffervac;		/* gcbuffer */
+	struct list_head fixupvac;		/* gcfixup */
+	struct list_head batchvac;		/* gcbatch */
+
+	/* Callback lists. */
+	struct list_head callbacklist;		/* gccallbackinfo */
+	struct list_head callbackvac;		/* gccallbackinfo */
+
+	/* Access locks. */
+	GCLOCK_TYPE batchlock;
+	GCLOCK_TYPE bufferlock;
+	GCLOCK_TYPE fixuplock;
+	GCLOCK_TYPE maplock;
+	GCLOCK_TYPE callbacklock;
+
+	/* Kernel table cache. */
+	struct gcfilterkernel *loadedfilter;	/* gcfilterkernel */
+	struct gcfiltercache filtercache[GC_FILTER_COUNT][GC_TAP_COUNT];
+
+	/* Temporary buffer descriptor. */
+	struct bvbuffdesc *tmpbuffdesc;
+	void *tmpbuff;
+};
+
+
+/*******************************************************************************
+ * Mapping structures.
+ */
+
+/* bvbuffmap struct attachment. */
+struct bvbuffmapinfo {
+	/* Mapped handle for the buffer. */
+	unsigned long handle;
+
+	/* Number of times the client explicitly mapped this buffer. */
+	int usermap;
+
+	/* Number of times implicit mapping happened. */
+	int automap;
+};
+
+
+/*******************************************************************************
+ * Color format.
+ */
+
+#define BVFMT_RGB	1
+#define BVFMT_YUV	2
+
+struct bvcomponent {
+	unsigned int shift;
+	unsigned int size;
+	unsigned int mask;
+};
+
+struct bvcsrgb {
+	struct bvcomponent r;
+	struct bvcomponent g;
+	struct bvcomponent b;
+	struct bvcomponent a;
+};
+
+struct bvformatxlate {
+	unsigned int type;
+	unsigned int bitspp;
+	unsigned int allocbitspp;
+	unsigned int format;
+	unsigned int swizzle;
+	unsigned int endian;
+	bool premultiplied;
+	bool zerofill;
+
+	union {
+		struct {
+			const struct bvcsrgb *comp;
+		} rgb;
+
+		struct {
+			unsigned int std;
+			unsigned int planecount;
+			unsigned int xsample;
+			unsigned int ysample;
+		} yuv;
+	} cs;
+};
+
+
+/*******************************************************************************
+ * Alpha blending.
+ */
+
+/* Alpha blending hardware configuration. */
+struct gcblendconfig {
+	unsigned char factor_mode;
+	unsigned char color_reverse;
+
+	bool src1used;
+	bool src2used;
+};
+
+/* Alpha blending descriptor. */
+struct gcalpha {
+	bool globalcolorenable;
+	unsigned int globalcolor;
+
+	struct gcblendconfig *k1;
+	struct gcblendconfig *k2;
+
+	struct gcblendconfig *srcconfig;
+	struct gcblendconfig *dstconfig;
+
+	bool src1used;
+	bool src2used;
+};
+
+
+/*******************************************************************************
+ * Rotation and mirror defines.
+ */
+
+#define GCREG_ROT_ANGLE_ROT0	0x0
+#define GCREG_ROT_ANGLE_ROT90	0x4
+#define GCREG_ROT_ANGLE_ROT180	0x5
+#define GCREG_ROT_ANGLE_ROT270	0x6
+
+#define ROT_ANGLE_INVALID	-1
+#define ROT_ANGLE_0		0
+#define ROT_ANGLE_90		1
+#define ROT_ANGLE_180		2
+#define ROT_ANGLE_270		3
+
+#define GCREG_MIRROR_NONE	0x0
+#define GCREG_MIRROR_X		0x1
+#define GCREG_MIRROR_Y		0x2
+#define GCREG_MIRROR_XY		0x3
+
+extern const unsigned int rotencoding[];
+
+
+/*******************************************************************************
+ * Surface descriptor.
+ */
+
+struct gcrectset {
+	/* Render rectangle as specified by the client. */
+	struct gcrect orig;
+
+	/* Clipped rectangle. */
+	struct gcrect clip;
+
+	/* Clipped rectangle adjusted for base address misalignment. */
+	struct gcrect adj;
+};
+
+struct gcsurface {
+	/* Surface change flags. */
+	bool surfdirty;
+	bool rectdirty;
+	bool destrectdirty;
+	bool cliprectdirty;
+
+	/* BLTsville source index (-1 for dst, 0 for src1 and 1 for src2). */
+	int index;
+
+	/* Surface buffer descriptor. */
+	union bvinbuff buf;
+
+	/* Geometry size as specified by the client. */
+	unsigned int width;
+	unsigned int height;
+
+	/* Geometry size adjusted for base address misalignment. */
+	unsigned int adjwidth;
+	unsigned int adjheight;
+
+	/* Physical size of the surface (adjusted and 0 degree rotated). */
+	unsigned int physwidth;
+	unsigned int physheight;
+
+	/* Plane strides. */
+	long stride1;
+	long stride2;
+	long stride3;
+
+	/* Base address alignment in pixels. */
+	int xpixalign;
+	int ypixalign;
+
+	/* Base address alignment in bytes. */
+	int bytealign1;
+	int bytealign2;
+	int bytealign3;
+
+	/* Surface format. */
+	struct bvformatxlate format;
+
+	/* Rotation angle. */
+	int angle;
+	int adjangle;
+
+	/* Render rectangles. */
+	struct gcrectset rect;
+
+	/* Aux render rectangles. */
+	bool haveaux;
+	struct gcrectset auxrect;
+
+	/* Mirror setting. */
+	unsigned int mirror;
+
+	/* ROP. */
+	unsigned short rop;
+
+	/* Blending info. */
+	struct gcalpha *gca;
+	bool globalcolorenable;
+	unsigned int globalcolor;
+	unsigned char srcglobalpremul;
+	unsigned char srcglobalmode;
+	unsigned char dstglobalmode;
+};
+
+
+/*******************************************************************************
+ * Batch structures.
+ */
+
+/* Operation finalization call. */
+struct gcbatch;
+typedef enum bverror (*gcbatchend) (struct bvbltparams *bvbltparams,
+				    struct gcbatch *gcbatch);
+
+/* Blit states. */
+struct gcblit {
+	/* Number of sources in the operation. */
+	unsigned int srccount;
+
+	/* Multi source enable flag. */
+	bool multisrc;
+
+	/* Computed destination rectangle coordinates; in multi-source
+	 * setup can be modified to match new destination and source
+	 * geometry. */
+	struct gcrect dstrect;
+
+	/* Block walker enable. */
+	bool blockenable;
+
+	/* Destination format and swizzle. */
+	unsigned int format;
+	unsigned int swizzle;
+	unsigned int endian;
+};
+
+/* Filter states. */
+struct gcfilter {
+	/* Kernel size. */
+	unsigned int horkernelsize;
+	unsigned int verkernelsize;
+
+	/* Scale factors. */
+	unsigned int horscalefactor;
+	unsigned int verscalefactor;
+};
+
+/* Batch header. */
+struct gcbatch {
+	/* Used to ID structure version. */
+	unsigned int structsize;
+
+	/* Batch change flags. */
+	unsigned long batchflags;
+
+	/* Pointer to the function to finalize the current operation. */
+	gcbatchend batchend;
+
+	/* State of the current operation. */
+	struct {
+		struct gcblit blit;
+		struct gcfilter filter;
+	} op;
+
+	/* Destination surface. */
+	struct gcsurface dstinfo;
+
+	/* Clipping deltas; used to correct the source coordinates for
+	 * single source blits. */
+	struct gcrect clipdelta;
+
+	/* Destination rectangle adjustment offsets. */
+	int dstoffsetX;
+	int dstoffsetY;
+
+#if GCDEBUG_ENABLE
+	/* Rectangle validation storage. */
+	struct bvrect prevdstrect;
+	struct bvrect prevsrc1rect;
+	struct bvrect prevsrc2rect;
+	struct bvrect prevmaskrect;
+#endif
+
+	/* Total size of the command buffer. */
+	unsigned int size;
+
+	/* Command buffer list (gcbuffer). */
+	struct list_head buffer;
+
+	/* Scheduled implicit unmappings (gcschedunmap). */
+	struct list_head unmap;
+
+	/* Batch linked list (gcbatch). */
+	struct list_head link;
+};
+
+
+/*******************************************************************************
+ * Internal API entries.
+ */
+
+/* Get the pointer to the context. */
+struct gccontext *get_context(void);
+
+/* Validation. */
+bool null_rect(struct gcrect *gcrect);
+bool valid_rect(struct gcsurface *gcsurface, struct gcrect *gcrect);
+
+/* Rotation processing. */
+void rotate_rect(int angle,
+		 struct gcsurface *gcsurface, struct gcrect *rect);
+void rotate_geom(int angle, struct gcsurface *gcsurface);
+void adjust_angle(struct gcsurface *srcinfo, struct gcsurface *dstinfo);
+void process_rotation(struct gcsurface *gcsurface);
+
+/* Parsers. */
+enum bverror parse_format(struct bvbltparams *bvbltparams,
+			  enum ocdformat ocdformat,
+			  struct bvformatxlate *format);
+enum bverror parse_blend(struct bvbltparams *bvbltparams,
+			 enum bvblend blend,
+			 struct gcalpha *gca);
+enum bverror parse_destination(struct bvbltparams *bvbltparams,
+			       struct gcbatch *gcbatch);
+enum bverror parse_source(struct bvbltparams *bvbltparams,
+			  struct gcbatch *batch,
+			  struct gcsurface *srcinfo,
+			  unsigned int index,
+			  unsigned short rop);
+enum bverror parse_scalemode(struct bvbltparams *bvbltparams,
+			     struct gcbatch *batch);
+
+/* Return surface alignment offset. */
+int get_pixel_offset(struct gcsurface *gcsurface, int offset);
+
+/* Buffer mapping. */
+enum bverror do_map(struct bvbuffdesc *bvbuffdesc,
+		    struct gcbatch *gcbatch,
+		    struct bvbuffmap **map);
+void do_unmap_implicit(struct gcbatch *gcbatch);
+
+/* Batch/command buffer management. */
+enum bverror do_end(struct bvbltparams *bvbltparams,
+		    struct gcbatch *gcbatch);
+enum bverror allocate_batch(struct bvbltparams *bvbltparams,
+			    struct gcbatch **gcbatch);
+void free_batch(struct gcbatch *gcbatch);
+enum bverror append_buffer(struct bvbltparams *bvbltparams,
+			   struct gcbatch *gcbatch,
+			   struct gcbuffer **gcbuffer);
+
+enum bverror add_fixup(struct bvbltparams *bvbltparams,
+		       struct gcbatch *gcbatch,
+		       unsigned int *fixup,
+		       unsigned int surfoffset);
+enum bverror claim_buffer(struct bvbltparams *bvbltparams,
+			  struct gcbatch *gcbatch,
+			  unsigned int size,
+			  void **buffer);
+
+/* Temporary buffer management. */
+enum bverror allocate_temp(struct bvbltparams *bvbltparams,
+			   unsigned int size);
+enum bverror free_temp(bool schedule);
+
+/* Program the destination. */
+enum bverror set_dst(struct bvbltparams *bltparams,
+		     struct gcbatch *batch,
+		     struct bvbuffmap *dstmap);
+
+/* Program blending. */
+enum bverror set_blending(struct bvbltparams *bvbltparams,
+			  struct gcbatch *batch,
+			  struct gcsurface *srcinfo);
+enum bverror set_blending_index(struct bvbltparams *bvbltparams,
+				struct gcbatch *batch,
+				struct gcsurface *srcinfo,
+				unsigned int index);
+
+/* Program YUV source. */
+void set_computeyuv(struct gcsurface *srcinfo, int x, int y);
+enum bverror set_yuvsrc(struct bvbltparams *bvbltparams,
+			struct gcbatch *batch,
+			struct gcsurface *srcinfo,
+			struct bvbuffmap *srcmap);
+enum bverror set_yuvsrc_index(struct bvbltparams *bvbltparams,
+			      struct gcbatch *batch,
+			      struct gcsurface *srcinfo,
+			      struct bvbuffmap *srcmap,
+			      unsigned int index);
+
+/* Rendering entry points. */
+enum bverror do_fill(struct bvbltparams *bltparams,
+		     struct gcbatch *gcbatch,
+		     struct gcsurface *srcinfo);
+enum bverror do_blit(struct bvbltparams *bltparams,
+		     struct gcbatch *gcbatch,
+		     struct gcsurface *srcinfo);
+enum bverror do_filter(struct bvbltparams *bvbltparams,
+		       struct gcbatch *gcbatch,
+		       struct gcsurface *srcinfo);
+
+#endif
diff --git a/drivers/misc/gcx/gcbv/gcbvdebug.c b/drivers/misc/gcx/gcbv/gcbvdebug.c
new file mode 100644
index 0000000..b6488e9
--- /dev/null
+++ b/drivers/misc/gcx/gcbv/gcbvdebug.c
@@ -0,0 +1,217 @@
+/*
+ * gcbvdebug.c
+ *
+ * Copyright (C) 2010-2011 Vivante Corporation.
+ *
+ * This package is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#include <linux/debugfs.h>
+#include <linux/seq_file.h>
+#include "gcbv.h"
+
+static struct dentry *debug_root;
+
+/*****************************************************************************/
+
+static struct {
+	unsigned int srccount;
+	unsigned int multisrc;
+	unsigned int align;
+	unsigned int flags_dst;
+	unsigned int flags_destrect;
+	unsigned int flags_cliprect;
+
+} finalize_batch_reason;
+
+static int bfr_show(struct seq_file *s, void *data)
+{
+	seq_printf(s, "      srccount: %d\n",
+		   finalize_batch_reason.srccount);
+	seq_printf(s, "      multisrc: %d\n",
+		   finalize_batch_reason.multisrc);
+	seq_printf(s, "         align: %d\n",
+		   finalize_batch_reason.align);
+	seq_printf(s, "     flags_dst: %d\n",
+		   finalize_batch_reason.flags_dst);
+	seq_printf(s, "flags_destrect: %d\n",
+		   finalize_batch_reason.flags_destrect);
+	seq_printf(s, "flags_cliprect: %d\n",
+		   finalize_batch_reason.flags_cliprect);
+
+	memset(&finalize_batch_reason, 0, sizeof(finalize_batch_reason));
+
+	return 0;
+}
+
+static int bfr_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, bfr_show, 0);
+}
+
+static const struct file_operations fops_bfr = {
+	.open    = bfr_open,
+	.write   = NULL,
+	.read    = seq_read,
+	.llseek  = seq_lseek,
+	.release = single_release,
+};
+
+void gcbv_debug_finalize_batch(unsigned int reason)
+{
+	if (reason & GCBV_BATCH_FINALIZE_SRCCOUNT)
+		finalize_batch_reason.srccount++;
+
+	if (reason & GCBV_BATCH_FINALIZE_MULTISRC)
+		finalize_batch_reason.multisrc++;
+
+	if (reason & GCBV_BATCH_FINALIZE_ALIGN)
+		finalize_batch_reason.align++;
+
+	if (reason & GCBV_BATCH_FINALIZE_FLAGS_DST)
+		finalize_batch_reason.flags_dst++;
+
+	if (reason & GCBV_BATCH_FINALIZE_FLAGS_CLIPRECT)
+		finalize_batch_reason.flags_cliprect++;
+
+	if (reason & GCBV_BATCH_FINALIZE_FLAGS_DESTRECT)
+		finalize_batch_reason.flags_destrect++;
+}
+
+/*****************************************************************************/
+
+#define MAX_BLT_SOURCES   8
+
+static struct gc_blt_status {
+	int totalCount;
+	long long int totalPixels;
+	int srcCount[MAX_BLT_SOURCES + 1];
+	long long int srcCountPixels[MAX_BLT_SOURCES + 1];
+
+	int two_dim_one_pass;
+	int two_dim_two_pass;
+	int one_dim;
+
+} blt_stats;
+
+void gcbv_debug_blt(int srccount, int dstWidth, int dstHeight)
+{
+	int pixels;
+
+	if (srccount > MAX_BLT_SOURCES)
+		return;
+
+	pixels = dstWidth * dstHeight;
+
+	blt_stats.srcCount[srccount]++;
+	blt_stats.srcCountPixels[srccount] += pixels;
+
+	blt_stats.totalPixels += pixels;
+	blt_stats.totalCount++;
+}
+
+void gcbv_debug_scaleblt(bool scalex, bool scaley, bool singlepass)
+{
+	if (scalex && scaley) {
+		if (singlepass)
+			blt_stats.two_dim_one_pass++;
+		else
+			blt_stats.two_dim_two_pass++;
+	} else
+		blt_stats.one_dim++;
+}
+
+static void blt_stats_reset(void)
+{
+	int i;
+
+	for (i = 1; i <= MAX_BLT_SOURCES; i++) {
+		blt_stats.srcCount[i] = 0;
+		blt_stats.srcCountPixels[i] = 0;
+	}
+
+	blt_stats.totalCount = 0;
+	blt_stats.totalPixels = 0;
+
+	blt_stats.two_dim_one_pass = 0;
+	blt_stats.two_dim_two_pass = 0;
+	blt_stats.one_dim = 0;
+}
+
+static int blt_stats_show(struct seq_file *s, void *data)
+{
+	int i;
+
+	seq_printf(s, "total blts: %d\n", blt_stats.totalCount);
+
+	if (blt_stats.totalCount) {
+		for (i = 1; i <= MAX_BLT_SOURCES; i++) {
+			int count = blt_stats.srcCount[i];
+
+			seq_printf(s, " %d src: %d (%d%%)\n",
+				   i,
+				   count,
+				   count * 100 / blt_stats.totalCount);
+		}
+	}
+
+	seq_printf(s, "total dst pixels: %lld\n", blt_stats.totalPixels);
+
+	if (blt_stats.totalPixels) {
+		for (i = 1; i <= MAX_BLT_SOURCES; i++) {
+			long long int count = blt_stats.srcCountPixels[i];
+			long long int total = blt_stats.totalPixels;
+
+			seq_printf(s, " %d src: %lld (%lld%%)\n",
+				   i,
+				   count,
+				   div64_s64(count * 100, total));
+		}
+	}
+
+	seq_printf(s, "scaled 2x2: %d\n", blt_stats.two_dim_two_pass);
+	seq_printf(s, "scaled 2x1: %d\n", blt_stats.two_dim_one_pass);
+	seq_printf(s, "scaled 1x1: %d\n", blt_stats.one_dim);
+
+	blt_stats_reset();
+
+	return 0;
+}
+
+static int blt_stats_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, blt_stats_show, 0);
+}
+
+static const struct file_operations fops_blt_stats = {
+	.open = blt_stats_open,
+	.read = seq_read,
+	.llseek = seq_lseek,
+	.release = single_release,
+};
+
+/*****************************************************************************/
+
+void gcbv_debug_init(void)
+{
+	debug_root = debugfs_create_dir("gcbv", NULL);
+	if (!debug_root)
+		return;
+
+	debugfs_create_file("blt_stats", 0664, debug_root, NULL,
+			    &fops_blt_stats);
+	debugfs_create_file("batch_finalize_reason", 0664, debug_root, NULL,
+			    &fops_bfr);
+}
+
+void gcbv_debug_shutdown(void)
+{
+	if (debug_root)
+		debugfs_remove_recursive(debug_root);
+}
diff --git a/drivers/misc/gcx/gcbv/gcbvdebug.h b/drivers/misc/gcx/gcbv/gcbvdebug.h
new file mode 100644
index 0000000..fec8d6d
--- /dev/null
+++ b/drivers/misc/gcx/gcbv/gcbvdebug.h
@@ -0,0 +1,26 @@
+/*
+ * gcbvdebug.h
+ *
+ * Copyright (C) 2010-2011 Vivante Corporation.
+ *
+ * This package is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#ifndef GCBVDEBUG_H
+#define GCBVDEBUG_H
+
+void gcbv_debug_init(void);
+void gcbv_debug_shutdown(void);
+
+void gcbv_debug_finalize_batch(unsigned int reason);
+
+void gcbv_debug_blt(int srccount, int dstWidth, int dstHeight);
+void gcbv_debug_scaleblt(bool scalex, bool scaley, bool singlepass);
+
+#endif
diff --git a/drivers/misc/gcx/gcbv/gcfill.c b/drivers/misc/gcx/gcbv/gcfill.c
new file mode 100644
index 0000000..df69434
--- /dev/null
+++ b/drivers/misc/gcx/gcbv/gcfill.c
@@ -0,0 +1,314 @@
+/*
+ * This file is provided under a dual BSD/GPLv2 license.  When using or
+ * redistributing this file, you may do so under either license.
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * Copyright(c) 2012 Vivante Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * BSD LICENSE
+ *
+ * Copyright(c) 2012 Vivante Corporation. 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 Vivante Corporation 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 AND FITNESS FOR A PARTICULAR PURPOSE
+ * 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.
+ */
+
+#include "gcbv.h"
+
+#define GCZONE_NONE		0
+#define GCZONE_ALL		(~0U)
+#define GCZONE_COLOR		(1 << 0)
+#define GCZONE_FILL		(1 << 1)
+
+GCDBG_FILTERDEF(fill, GCZONE_NONE,
+		"color",
+		"fill")
+
+
+static inline unsigned int extract_component(unsigned int pixel,
+					     const struct bvcomponent *desc,
+					     bool zerofill)
+{
+	unsigned int component;
+	unsigned int component8;
+
+	component = (pixel & desc->mask) >> desc->shift;
+	GCDBG(GCZONE_COLOR, "mask=0x%08X, shift=%d, component=0x%08X\n",
+		desc->mask, desc->shift, component);
+
+	switch (desc->size) {
+	case 0:
+		component8 = zerofill ? 0x00 : 0xFF;
+		GCDBG(GCZONE_COLOR, "component8=0x%08X\n", component8);
+		break;
+
+	case 1:
+		component8 = component ? 0xFF : 0x00;
+		GCDBG(GCZONE_COLOR, "component8=0x%08X\n", component8);
+		break;
+
+	case 4:
+		component8 = component | (component << 4);
+		GCDBG(GCZONE_COLOR, "component8=0x%08X\n", component8);
+		break;
+
+	case 5:
+		component8 = (component << 3) | (component >> 2);
+		GCDBG(GCZONE_COLOR, "component8=0x%08X\n", component8);
+		break;
+
+	case 6:
+		component8 = (component << 2) | (component >> 4);
+		GCDBG(GCZONE_COLOR, "component8=0x%08X\n", component8);
+		break;
+
+	default:
+		component8 = component;
+		GCDBG(GCZONE_COLOR, "component8=0x%08X\n", component8);
+	}
+
+	return component8;
+}
+
+static unsigned int getinternalcolor(void *ptr, struct bvformatxlate *format)
+{
+	unsigned int srcpixel, dstpixel;
+	unsigned int r, g, b, a;
+
+	switch (format->bitspp) {
+	case 16:
+		srcpixel = *(unsigned short *) ptr;
+		GCDBG(GCZONE_COLOR, "srcpixel=0x%08X\n", srcpixel);
+		break;
+
+	case 32:
+		srcpixel = *(unsigned int *) ptr;
+		GCDBG(GCZONE_COLOR, "srcpixel=0x%08X\n", srcpixel);
+		break;
+
+	default:
+		srcpixel = 0;
+		GCDBG(GCZONE_COLOR, "srcpixel=0x%08X\n", srcpixel);
+	}
+
+	r = extract_component(srcpixel, &format->cs.rgb.comp->r,
+			      format->zerofill);
+	g = extract_component(srcpixel, &format->cs.rgb.comp->g,
+			      format->zerofill);
+	b = extract_component(srcpixel, &format->cs.rgb.comp->b,
+			      format->zerofill);
+	a = extract_component(srcpixel, &format->cs.rgb.comp->a,
+			      format->zerofill);
+
+	GCDBG(GCZONE_COLOR, "(r,g,b,a)=0x%02X,0x%02X,0x%02X,0x%02X\n",
+	      r, g, b, a);
+
+	dstpixel = (a << 24) | (r << 16) | (g <<  8) | b;
+
+	GCDBG(GCZONE_COLOR, "dstpixel=0x%08X\n", dstpixel);
+
+	return dstpixel;
+}
+
+enum bverror do_fill(struct bvbltparams *bvbltparams,
+		     struct gcbatch *batch,
+		     struct gcsurface *srcinfo)
+{
+	enum bverror bverror;
+	struct gccontext *gccontext = get_context();
+	struct gcsurface *dstinfo;
+	struct gcmofill *gcmofill;
+	unsigned char *fillcolorptr;
+	struct bvbuffmap *dstmap = NULL;
+	int physleft, phystop;
+	struct gcrect *srcorig;
+	struct gcrect *dstadj;
+
+	GCENTER(GCZONE_FILL);
+
+	/* Get a shortcut to the destination surface descriptor. */
+	dstinfo = &batch->dstinfo;
+
+	/* Only RGB source is supported. */
+	if (srcinfo->format.type != BVFMT_RGB) {
+		BVSETBLTERROR((srcinfo->index == 0)
+					? BVERR_SRC1GEOM_FORMAT
+					: BVERR_SRC2GEOM_FORMAT,
+			      "only RGB source is supported for fill.");
+		goto exit;
+	}
+
+	/* Finish previous batch if any. */
+	bverror = batch->batchend(bvbltparams, batch);
+	if (bverror != BVERR_NONE)
+		goto exit;
+
+	/* Parse destination parameters. */
+	bverror = parse_destination(bvbltparams, batch);
+	if (bverror != BVERR_NONE)
+		goto exit;
+
+	/* Ignore the blit if destination rectangle is empty. */
+	if (null_rect(&dstinfo->rect.clip)) {
+		GCDBG(GCZONE_FILL, "empty destination rectangle.\n");
+		goto exit;
+	}
+
+	/* Map the destination. */
+	bverror = do_map(bvbltparams->dstdesc, batch, &dstmap);
+	if (bverror != BVERR_NONE) {
+		bvbltparams->errdesc = gccontext->bverrorstr;
+		goto exit;
+	}
+
+	/* Set the new destination. */
+	bverror = set_dst(bvbltparams, batch, dstmap);
+	if (bverror != BVERR_NONE)
+		goto exit;
+
+	/***********************************************************************
+	** Allocate command buffer.
+	*/
+
+	bverror = claim_buffer(bvbltparams, batch,
+			       sizeof(struct gcmofill),
+			       (void **) &gcmofill);
+	if (bverror != BVERR_NONE)
+		goto exit;
+
+	/***********************************************************************
+	** Set dummy source.
+	*/
+
+	/* Set surface dummy width and height. */
+	gcmofill->src.rotation_ldst = gcmofillsrc_rotation_ldst;
+	gcmofill->src.rotation.raw = 0;
+	gcmofill->src.rotation.reg.surf_width = 1;
+	gcmofill->src.config.raw = 0;
+
+	gcmofill->src.rotationheight_ldst = gcmofillsrc_rotationheight_ldst;
+	gcmofill->src.rotationheight.reg.height = 1;
+	gcmofill->src.rotationangle.raw = 0;
+	gcmofill->src.rotationangle.reg.dst = rotencoding[dstinfo->angle];
+	gcmofill->src.rotationangle.reg.dst_mirror = GCREG_MIRROR_NONE;
+
+	/* Disable alpha blending. */
+	gcmofill->src.alphacontrol_ldst = gcmofillsrc_alphacontrol_ldst;
+	gcmofill->src.alphacontrol.raw = 0;
+	gcmofill->src.alphacontrol.reg.enable = GCREG_ALPHA_CONTROL_ENABLE_OFF;
+
+	/***********************************************************************
+	** Set fill color.
+	*/
+
+	/* Get source rectangle shortcut. */
+	srcorig = &srcinfo->rect.orig;
+
+	switch (srcinfo->angle) {
+	case ROT_ANGLE_0:
+		physleft = srcorig->left;
+		phystop  = srcorig->top;
+		break;
+
+	case ROT_ANGLE_90:
+		physleft = srcorig->top;
+		phystop  = srcinfo->width - srcorig->left - 1;
+		break;
+
+	case ROT_ANGLE_180:
+		physleft = srcinfo->width  - srcorig->left - 1;
+		phystop  = srcinfo->height - srcorig->top  - 1;
+		break;
+
+	case ROT_ANGLE_270:
+		physleft = srcinfo->height - srcorig->top  - 1;
+		phystop  = srcorig->left;
+		break;
+
+	default:
+		physleft = 0;
+		phystop  = 0;
+		GCERR("invalid source angle %d.\n", srcinfo->angle);
+	}
+
+	fillcolorptr
+		= (unsigned char *) srcinfo->buf.desc->virtaddr
+		+ phystop * srcinfo->stride1
+		+ physleft * srcinfo->format.bitspp / 8;
+
+	gcmofill->clearcolor_ldst = gcmofill_clearcolor_ldst;
+	gcmofill->clearcolor.raw = getinternalcolor(fillcolorptr,
+						    &srcinfo->format);
+
+	/***********************************************************************
+	** Configure and start fill.
+	*/
+
+	/* Set destination configuration. */
+	gcmofill->dstconfig_ldst = gcmofill_dstconfig_ldst;
+	gcmofill->dstconfig.raw = 0;
+	gcmofill->dstconfig.reg.swizzle = dstinfo->format.swizzle;
+	gcmofill->dstconfig.reg.format = dstinfo->format.format;
+	gcmofill->dstconfig.reg.endian = dstinfo->format.endian;
+	gcmofill->dstconfig.reg.command = GCREG_DEST_CONFIG_COMMAND_CLEAR;
+
+	/* Set ROP3. */
+	gcmofill->rop_ldst = gcmofill_rop_ldst;
+	gcmofill->rop.raw = 0;
+	gcmofill->rop.reg.type = GCREG_ROP_TYPE_ROP3;
+	gcmofill->rop.reg.fg = srcinfo->rop;
+
+	/* Set START_DE command. */
+	gcmofill->startde.cmd.fld = gcfldstartde;
+
+	/* Set destination rectangle. */
+	dstadj = &dstinfo->rect.adj;
+	gcmofill->rect.left = dstadj->left;
+	gcmofill->rect.top = dstadj->top;
+	gcmofill->rect.right = dstadj->right;
+	gcmofill->rect.bottom = dstadj->bottom;
+
+exit:
+	GCEXITARG(GCZONE_FILL, "bv%s = %d\n",
+		  (bverror == BVERR_NONE) ? "result" : "error", bverror);
+	return bverror;
+}
diff --git a/drivers/misc/gcx/gcbv/gcfilter.c b/drivers/misc/gcx/gcbv/gcfilter.c
new file mode 100644
index 0000000..43d3615
--- /dev/null
+++ b/drivers/misc/gcx/gcbv/gcfilter.c
@@ -0,0 +1,1490 @@
+/*
+ * This file is provided under a dual BSD/GPLv2 license.  When using or
+ * redistributing this file, you may do so under either license.
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * Copyright(c) 2012 Vivante Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * BSD LICENSE
+ *
+ * Copyright(c) 2012 Vivante Corporation. 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 Vivante Corporation 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 AND FITNESS FOR A PARTICULAR PURPOSE
+ * 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.
+ */
+
+#include "gcbv.h"
+
+#define GCZONE_NONE		0
+#define GCZONE_ALL		(~0U)
+#define GCZONE_KERNEL		(1 << 0)
+#define GCZONE_FILTER		(1 << 1)
+#define GCZONE_BLEND		(1 << 2)
+#define GCZONE_TYPE		(1 << 3)
+#define GCZONE_SRC		(1 << 4)
+#define GCZONE_DEST		(1 << 5)
+#define GCZONE_SURF		(1 << 6)
+
+GCDBG_FILTERDEF(filter, GCZONE_NONE,
+		"kernel",
+		"filter",
+		"blend",
+		"type",
+		"src",
+		"dest",
+		"surf")
+
+
+/*******************************************************************************
+ * Miscellaneous defines.
+ */
+
+#define GC_BYTES_PER_CACHELINE	(64)
+#define GC_BITS_PER_CACHELINE	(GC_BYTES_PER_CACHELINE * 8)
+#define GC_CACHELINE_ALIGN_16	(GC_BITS_PER_CACHELINE / 16 - 1)
+#define GC_CACHELINE_ALIGN_32	(GC_BITS_PER_CACHELINE / 32 - 1)
+
+enum gcscaletype {
+	GC_SCALE_OPF,
+	GC_SCALE_HOR,
+	GC_SCALE_VER,
+	GC_SCALE_HOR_FLIPPED,
+	GC_SCALE_VER_FLIPPED
+};
+
+/*******************************************************************************
+ * Scale factor format: unsigned 1.31 fixed point.
+ */
+
+#define GC_SCALE_TYPE		unsigned int
+#define GC_SCALE_FRACTION	31
+#define GC_SCALE_ONE		((GC_SCALE_TYPE) (1 << GC_SCALE_FRACTION))
+
+
+/*******************************************************************************
+ * X coordinate format: signed 4.28 fixed point.
+ */
+
+#define GC_COORD_TYPE		int
+#define GC_COORD_FRACTION	28
+#define GC_COORD_PI		((GC_COORD_TYPE) 0x3243F6C0)
+#define GC_COORD_2OVERPI	((GC_COORD_TYPE) 0x0A2F9832)
+#define GC_COORD_PIOVER2	((GC_COORD_TYPE) 0x1921FB60)
+#define GC_COORD_ZERO		((GC_COORD_TYPE) 0)
+#define GC_COORD_HALF		((GC_COORD_TYPE) (1 << (GC_COORD_FRACTION - 1)))
+#define GC_COORD_ONE		((GC_COORD_TYPE) (1 << GC_COORD_FRACTION))
+#define GC_COORD_NEGONE		((GC_COORD_TYPE) (~GC_COORD_ONE + 1))
+#define GC_COORD_SUBPIX_STEP	((GC_COORD_TYPE) \
+				(1 << (GC_COORD_FRACTION - GC_PHASE_BITS)))
+
+
+/*******************************************************************************
+ * Hardware coefficient format: signed 2.14 fixed point.
+ */
+
+#define GC_COEF_TYPE		short
+#define GC_COEF_FRACTION	14
+#define GC_COEF_ZERO		((GC_COEF_TYPE) 0)
+#define GC_COEF_ONE		((GC_COEF_TYPE) (1 << GC_COEF_FRACTION))
+#define GC_COEF_NEGONE		((GC_COEF_TYPE) (~GC_COEF_ONE + 1))
+
+
+/*******************************************************************************
+ * Weight sum format: x.28 fixed point.
+ */
+
+#define GC_SUM_TYPE		long long
+#define GC_SUM_FRACTION		GC_COORD_FRACTION
+
+
+/*******************************************************************************
+ * Math shortcuts.
+ */
+
+#define computescale(dstsize, srcsize) ((GC_SCALE_TYPE) \
+	div_u64(((u64) (dstsize)) << GC_SCALE_FRACTION, (srcsize)) \
+)
+
+#define normweight(weight, sum) ((GC_COORD_TYPE) \
+	div64_s64(((s64) (weight)) << GC_COORD_FRACTION, (sum)) \
+)
+
+#define convertweight(weight) ((GC_COEF_TYPE) \
+	((weight) >> (GC_COORD_FRACTION - GC_COEF_FRACTION)) \
+)
+
+
+/*******************************************************************************
+ * Fixed point SINE function. Takes a positive value in range [0..pi/2].
+ */
+
+static GC_COORD_TYPE sine(GC_COORD_TYPE x)
+{
+	static const GC_COORD_TYPE sinetable[] = {
+		0x00000000, 0x001FFFEB, 0x003FFF55, 0x005FFDC0,
+		0x007FFAAB, 0x009FF596, 0x00BFEE01, 0x00DFE36C,
+		0x00FFD557, 0x011FC344, 0x013FACB2, 0x015F9120,
+		0x017F7010, 0x019F4902, 0x01BF1B78, 0x01DEE6F2,
+		0x01FEAAEE, 0x021E66F0, 0x023E1A7C, 0x025DC50C,
+		0x027D6624, 0x029CFD48, 0x02BC89F8, 0x02DC0BB8,
+		0x02FB8204, 0x031AEC64, 0x033A4A5C, 0x03599B64,
+		0x0378DF08, 0x039814CC, 0x03B73C2C, 0x03D654B0,
+		0x03F55DDC, 0x04145730, 0x04334030, 0x04521868,
+		0x0470DF58, 0x048F9488, 0x04AE3770, 0x04CCC7A8,
+		0x04EB44A8, 0x0509ADF8, 0x05280328, 0x054643B0,
+		0x05646F28, 0x05828508, 0x05A084E0, 0x05BE6E38,
+		0x05DC4098, 0x05F9FB80, 0x06179E88, 0x06352928,
+		0x06529AF8, 0x066FF380, 0x068D3248, 0x06AA56D8,
+		0x06C760C0, 0x06E44F90, 0x070122C8, 0x071DD9F8,
+		0x073A74B8, 0x0756F290, 0x07735308, 0x078F95B0,
+		0x07ABBA20, 0x07C7BFD8, 0x07E3A678, 0x07FF6D88,
+		0x081B14A0, 0x08369B40, 0x08520110, 0x086D4590,
+		0x08886860, 0x08A36910, 0x08BE4730, 0x08D90250,
+		0x08F39A20, 0x090E0E10, 0x09285DD0, 0x094288E0,
+		0x095C8EF0, 0x09766F90, 0x09902A60, 0x09A9BEE0,
+		0x09C32CC0, 0x09DC7390, 0x09F592F0, 0x0A0E8A70,
+		0x0A2759C0, 0x0A400070, 0x0A587E20, 0x0A70D270,
+		0x0A88FD00, 0x0AA0FD60, 0x0AB8D350, 0x0AD07E50,
+		0x0AE7FE10, 0x0AFF5230, 0x0B167A50, 0x0B2D7610,
+		0x0B444520, 0x0B5AE730, 0x0B715BC0, 0x0B87A290,
+		0x0B9DBB40, 0x0BB3A580, 0x0BC960F0, 0x0BDEED30,
+		0x0BF44A00, 0x0C0976F0, 0x0C1E73D0, 0x0C334020,
+		0x0C47DBB0, 0x0C5C4620, 0x0C707F20, 0x0C848660,
+		0x0C985B80, 0x0CABFE50, 0x0CBF6E60, 0x0CD2AB80,
+		0x0CE5B550, 0x0CF88B80, 0x0D0B2DE0, 0x0D1D9C10,
+		0x0D2FD5C0, 0x0D41DAB0, 0x0D53AAA0, 0x0D654540,
+		0x0D76AA40, 0x0D87D970, 0x0D98D280, 0x0DA99530,
+		0x0DBA2140, 0x0DCA7650, 0x0DDA9450, 0x0DEA7AD0,
+		0x0DFA29B0, 0x0E09A0B0, 0x0E18DF80, 0x0E27E5F0,
+		0x0E36B3C0, 0x0E4548B0, 0x0E53A490, 0x0E61C720,
+		0x0E6FB020, 0x0E7D5F70, 0x0E8AD4C0, 0x0E980FF0,
+		0x0EA510B0, 0x0EB1D6F0, 0x0EBE6260, 0x0ECAB2D0,
+		0x0ED6C810, 0x0EE2A200, 0x0EEE4070, 0x0EF9A310,
+		0x0F04C9E0, 0x0F0FB490, 0x0F1A6300, 0x0F24D510,
+		0x0F2F0A80, 0x0F390340, 0x0F42BF10, 0x0F4C3DE0,
+		0x0F557F70, 0x0F5E83C0, 0x0F674A80, 0x0F6FD3B0,
+		0x0F781F20, 0x0F802CB0, 0x0F87FC40, 0x0F8F8DA0,
+		0x0F96E0D0, 0x0F9DF5B0, 0x0FA4CC00, 0x0FAB63D0,
+		0x0FB1BCF0, 0x0FB7D740, 0x0FBDB2B0, 0x0FC34F30,
+		0x0FC8ACA0, 0x0FCDCAF0, 0x0FD2AA10, 0x0FD749E0,
+		0x0FDBAA50, 0x0FDFCB50, 0x0FE3ACD0, 0x0FE74EC0,
+		0x0FEAB110, 0x0FEDD3C0, 0x0FF0B6B0, 0x0FF359F0,
+		0x0FF5BD50, 0x0FF7E0E0, 0x0FF9C490, 0x0FFB6850,
+		0x0FFCCC30, 0x0FFDF010, 0x0FFED400, 0x0FFF77F0,
+		0x0FFFDBF0, 0x0FFFFFE0, 0x0FFFE3D0, 0x0FFF87D0,
+		0x0FFEEBC0, 0x0FFE0FC0, 0x0FFCF3D0, 0x0FFB97E0
+	};
+
+	enum {
+		indexwidth = 8,
+		intwidth = 1,
+		indexshift = intwidth
+			   + GC_COORD_FRACTION
+			   - indexwidth
+	};
+
+	unsigned int p1, p2;
+	GC_COORD_TYPE p1x, p2x;
+	GC_COORD_TYPE p1y, p2y;
+	GC_COORD_TYPE dx, dy;
+	GC_COORD_TYPE a, b;
+	GC_COORD_TYPE result;
+
+	/* Determine the indices of two closest points in the table. */
+	p1 = ((unsigned int) x) >> indexshift;
+	p2 =  p1 + 1;
+
+	if ((p1 >= countof(sinetable)) || (p2 >= countof(sinetable))) {
+		GCERR("invalid table index.\n");
+		return GC_COORD_ZERO;
+	}
+
+	/* Determine the coordinates of the two closest points.  */
+	p1x = p1 << indexshift;
+	p2x = p2 << indexshift;
+
+	p1y = sinetable[p1];
+	p2y = sinetable[p2];
+
+	/* Determine the deltas. */
+	dx = p2x - p1x;
+	dy = p2y - p1y;
+
+	/* Find the slope and the y-intercept. */
+	b = (GC_COORD_TYPE) div64_s64(((s64) dy) << GC_COORD_FRACTION, dx);
+	a = p1y - (GC_COORD_TYPE) (((s64) b * p1x) >> GC_COORD_FRACTION);
+
+	/* Compute the result. */
+	result = a + (GC_COORD_TYPE) (((s64) b * x) >> GC_COORD_FRACTION);
+	return result;
+}
+
+
+/*******************************************************************************
+ * SINC function used in filter kernel generation.
+ */
+
+static GC_COORD_TYPE sinc_filter(GC_COORD_TYPE x, int radius)
+{
+	GC_COORD_TYPE result;
+	s64 radius64;
+	s64 pit, pitd;
+	s64 normpit, normpitd;
+	int negpit, negpitd;
+	int quadpit, quadpitd;
+	GC_COORD_TYPE sinpit, sinpitd;
+	GC_COORD_TYPE f1, f2;
+
+	if (x == GC_COORD_ZERO)
+		return GC_COORD_ONE;
+
+	radius64 = abs(radius) << GC_COORD_FRACTION;
+	if (x > radius64)
+		return GC_COORD_ZERO;
+
+	pit  = (((s64) GC_COORD_PI) * x) >> GC_COORD_FRACTION;
+	pitd = div_s64(pit, radius);
+
+	/* Sine table only has values for the first positive quadrant,
+	 * remove the sign here. */
+	if (pit < 0) {
+		normpit = -pit;
+		negpit = 1;
+	} else {
+		normpit = pit;
+		negpit = 0;
+	}
+
+	if (pitd < 0) {
+		normpitd = -pitd;
+		negpitd = 1;
+	} else {
+		normpitd = pitd;
+		negpitd = 0;
+	}
+
+	/* Determine which quadrant we are in. */
+	quadpit = (int) ((normpit * GC_COORD_2OVERPI)
+		>> (2 * GC_COORD_FRACTION));
+	quadpitd = (int) ((normpitd * GC_COORD_2OVERPI)
+		>> (2 * GC_COORD_FRACTION));
+
+	/* Move coordinates to the first quadrant. */
+	normpit -= (s64) GC_COORD_PIOVER2 * quadpit;
+	normpitd -= (s64) GC_COORD_PIOVER2 * quadpitd;
+
+	/* Normalize the quadrant numbers. */
+	quadpit %= 4;
+	quadpitd %= 4;
+
+	/* Flip the coordinates if necessary. */
+	if ((quadpit == 1) || (quadpit == 3))
+		normpit = GC_COORD_PIOVER2 - normpit;
+
+	if ((quadpitd == 1) || (quadpitd == 3))
+		normpitd = GC_COORD_PIOVER2 - normpitd;
+
+	sinpit = sine((GC_COORD_TYPE) normpit);
+	sinpitd = sine((GC_COORD_TYPE) normpitd);
+
+	/* Negate depending on the quadrant. */
+	if (negpit) {
+		if ((quadpit == 0) || (quadpit == 1))
+			sinpit = -sinpit;
+	} else {
+		if ((quadpit == 2) || (quadpit == 3))
+			sinpit = -sinpit;
+	}
+
+	if (negpitd) {
+		if ((quadpitd == 0) || (quadpitd == 1))
+			sinpitd = -sinpitd;
+	} else {
+		if ((quadpitd == 2) || (quadpitd == 3))
+			sinpitd = -sinpitd;
+	}
+
+	f1 = (GC_COORD_TYPE)
+	     div64_s64(((s64) sinpit) << GC_COORD_FRACTION, pit);
+	f2 = (GC_COORD_TYPE)
+	     div64_s64(((s64) sinpitd) << GC_COORD_FRACTION, pitd);
+
+	result = (GC_COORD_TYPE) ((((s64) f1) * f2)
+	       >> GC_COORD_FRACTION);
+
+	return result;
+}
+
+
+/*******************************************************************************
+ * Filter kernel generator based on SINC function.
+ */
+
+static void calculate_sync_filter(struct gcfilterkernel *gcfilterkernel)
+{
+	GC_SCALE_TYPE scale;
+	GC_COORD_TYPE subpixset[GC_TAP_COUNT];
+	GC_COORD_TYPE subpixeloffset;
+	GC_COORD_TYPE x, weight;
+	GC_SUM_TYPE weightsum;
+	short convweightsum;
+	int kernelhalf, padding;
+	int subpixpos, kernelpos;
+	short *kernelarray;
+	short count, adjustfrom, adjustment;
+	int index;
+
+	/* Compute the scale factor. */
+	scale = (gcfilterkernel->dstsize >= gcfilterkernel->srcsize)
+	      ? GC_SCALE_ONE
+	      : computescale(gcfilterkernel->dstsize, gcfilterkernel->srcsize);
+
+	/* Calculate the kernel half. */
+	kernelhalf = (int) (gcfilterkernel->kernelsize >> 1);
+
+	/* Init the subpixel offset. */
+	subpixeloffset = GC_COORD_HALF;
+
+	/* Determine kernel padding size. */
+	padding = (GC_TAP_COUNT - gcfilterkernel->kernelsize) / 2;
+
+	/* Set initial kernel array pointer. */
+	kernelarray = gcfilterkernel->kernelarray;
+
+	/* Loop through each subpixel. */
+	for (subpixpos = 0; subpixpos < GC_PHASE_LOAD_COUNT; subpixpos += 1) {
+		/* Compute weights. */
+		weightsum = GC_COORD_ZERO;
+		for (kernelpos = 0; kernelpos < GC_TAP_COUNT; kernelpos += 1) {
+			/* Determine the current index. */
+			index = kernelpos - padding;
+
+			/* Pad with zeros left side. */
+			if (index < 0) {
+				subpixset[kernelpos] = GC_COORD_ZERO;
+				continue;
+			}
+
+			/* Pad with zeros right side. */
+			if (index >= (int) gcfilterkernel->kernelsize) {
+				subpixset[kernelpos] = GC_COORD_ZERO;
+				continue;
+			}
+
+			/* "Filter off" case. */
+			if (gcfilterkernel->kernelsize == 1) {
+				subpixset[kernelpos] = GC_COORD_ONE;
+
+				/* Update the sum of the weights. */
+				weightsum += GC_COORD_ONE;
+				continue;
+			}
+
+			/* Compute X coordinate. */
+			x = ((index - kernelhalf) << GC_COORD_FRACTION)
+			  + subpixeloffset;
+
+			/* Scale the coordinate. */
+			x = (GC_COORD_TYPE)
+			    ((((s64) x) * scale) >> GC_SCALE_FRACTION);
+
+			/* Compute the weight. */
+			subpixset[kernelpos] = sinc_filter(x, kernelhalf);
+
+			/* Update the sum of the weights. */
+			weightsum += subpixset[kernelpos];
+		}
+
+		/* Convert the weights to the hardware format. */
+		convweightsum = 0;
+		for (kernelpos = 0; kernelpos < GC_TAP_COUNT; kernelpos += 1) {
+			/* Normalize the current weight. */
+			weight = normweight(subpixset[kernelpos], weightsum);
+
+			/* Convert the weight to fixed point. */
+			if (weight == GC_COORD_ZERO)
+				kernelarray[kernelpos] = GC_COEF_ZERO;
+			else if (weight >= GC_COORD_ONE)
+				kernelarray[kernelpos] = GC_COEF_ONE;
+			else if (weight <= GC_COORD_NEGONE)
+				kernelarray[kernelpos] = GC_COEF_NEGONE;
+			else
+				kernelarray[kernelpos] = convertweight(weight);
+
+			/* Compute the sum of all coefficients. */
+			convweightsum += kernelarray[kernelpos];
+		}
+
+		/* Adjust the fixed point coefficients so that the sum is 1. */
+		count = GC_COEF_ONE - convweightsum;
+		if (count < 0) {
+			count = -count;
+			adjustment = -1;
+		} else {
+			adjustment = 1;
+		}
+
+		if (count > GC_TAP_COUNT) {
+			GCERR("adjust count is too high = %d\n", count);
+		} else {
+			adjustfrom = (GC_TAP_COUNT - count) / 2;
+			for (kernelpos = 0; kernelpos < count; kernelpos += 1)
+				kernelarray[adjustfrom + kernelpos]
+					+= adjustment;
+		}
+
+		/* Advance the array pointer. */
+		kernelarray += GC_TAP_COUNT;
+
+		/* Advance to the next subpixel. */
+		subpixeloffset -= GC_COORD_SUBPIX_STEP;
+	}
+}
+
+
+/*******************************************************************************
+ * Loads a filter into the GPU.
+ */
+
+static enum bverror load_filter(struct bvbltparams *bvbltparams,
+				struct gcbatch *batch,
+				enum gcfiltertype type,
+				unsigned int kernelsize,
+				unsigned int scalefactor,
+				unsigned int srcsize,
+				unsigned int dstsize,
+				struct gccmdldstate arraystate)
+{
+	enum bverror bverror = BVERR_NONE;
+	struct gccontext *gccontext = get_context();
+	struct gcfiltercache *filtercache;
+	struct list_head *filterlist;
+	struct list_head *filterhead;
+	struct gcfilterkernel *gcfilterkernel;
+	struct gcmofilterkernel *gcmofilterkernel;
+
+	GCDBG(GCZONE_KERNEL, "kernelsize = %d\n", kernelsize);
+	GCDBG(GCZONE_KERNEL, "srcsize = %d\n", srcsize);
+	GCDBG(GCZONE_KERNEL, "dstsize = %d\n", dstsize);
+	GCDBG(GCZONE_KERNEL, "scalefactor = 0x%08X\n", scalefactor);
+
+	/* Is the filter already loaded? */
+	if ((gccontext->loadedfilter != NULL) &&
+	    (gccontext->loadedfilter->type == type) &&
+	    (gccontext->loadedfilter->kernelsize == kernelsize) &&
+	    (gccontext->loadedfilter->scalefactor == scalefactor)) {
+		GCDBG(GCZONE_KERNEL, "filter already computed.\n");
+		gcfilterkernel = gccontext->loadedfilter;
+		goto load;
+	}
+
+	/* Get the proper filter cache. */
+	filtercache = &gccontext->filtercache[type][kernelsize];
+	filterlist = &filtercache->list;
+
+	/* Try to find existing filter. */
+	GCDBG(GCZONE_KERNEL, "scanning for existing filter.\n");
+	list_for_each(filterhead, filterlist) {
+		gcfilterkernel = list_entry(filterhead,
+					    struct gcfilterkernel,
+					    link);
+		if (gcfilterkernel->scalefactor == scalefactor) {
+			GCDBG(GCZONE_KERNEL, "filter found @ 0x%08X.\n",
+			      (unsigned int) gcfilterkernel);
+			break;
+		}
+	}
+
+	/* Found the filter? */
+	if (filterhead != filterlist) {
+		/* Move the filter to the head of the list. */
+		if (filterlist->next != filterhead) {
+			GCDBG(GCZONE_KERNEL, "moving to the head.\n");
+			list_move(filterhead, filterlist);
+		}
+	} else {
+		GCDBG(GCZONE_KERNEL, "filter not found.\n");
+		if (filtercache->count == GC_FILTER_CACHE_MAX) {
+			GCDBG(GCZONE_KERNEL,
+			      "reached the maximum number of filters.\n");
+			filterhead = filterlist->prev;
+			list_move(filterhead, filterlist);
+
+			gcfilterkernel = list_entry(filterhead,
+						    struct gcfilterkernel,
+						    link);
+		} else {
+			GCDBG(GCZONE_KERNEL, "allocating new filter.\n");
+			gcfilterkernel = gcalloc(struct gcfilterkernel,
+						 sizeof(struct gcfilterkernel));
+			if (gcfilterkernel == NULL) {
+				BVSETBLTERROR(BVERR_OOM,
+					      "filter allocation failed");
+				goto exit;
+			}
+
+			list_add(&gcfilterkernel->link, filterlist);
+		}
+
+		/* Update the number of filters. */
+		filtercache->count += 1;
+
+		/* Initialize the filter. */
+		gcfilterkernel->type = type;
+		gcfilterkernel->kernelsize = kernelsize;
+		gcfilterkernel->srcsize = srcsize;
+		gcfilterkernel->dstsize = dstsize;
+		gcfilterkernel->scalefactor = scalefactor;
+
+		/* Compute the coefficients. */
+		calculate_sync_filter(gcfilterkernel);
+	}
+
+load:
+	GCDBG(GCZONE_KERNEL, "loading filter.\n");
+
+	/* Load the filter. */
+	bverror = claim_buffer(bvbltparams, batch,
+			       sizeof(struct gcmofilterkernel),
+			       (void **) &gcmofilterkernel);
+	if (bverror != BVERR_NONE)
+		goto exit;
+
+	gcmofilterkernel->kernelarray_ldst = arraystate;
+	memcpy(&gcmofilterkernel->kernelarray,
+	       gcfilterkernel->kernelarray,
+	       sizeof(gcfilterkernel->kernelarray));
+
+	/* Set the filter. */
+	gccontext->loadedfilter = gcfilterkernel;
+
+exit:
+	return bverror;
+}
+
+
+/*******************************************************************************
+ * Compute the scale factor.
+ */
+
+static inline unsigned int get_scale_factor(unsigned int srcsize,
+					    unsigned int dstsize)
+{
+	if ((srcsize <= 1) || (dstsize <= 1))
+		return 0;
+
+	return ((srcsize - 1) << 16) / (dstsize - 1);
+}
+
+
+/*******************************************************************************
+ * Rasterizer setup.
+ */
+
+static enum bverror startvr(struct bvbltparams *bvbltparams,
+			    struct gcbatch *batch,
+			    struct bvbuffmap *srcmap,
+			    struct bvbuffmap *dstmap,
+			    struct gcsurface *srcinfo,
+			    struct gcsurface *dstinfo,
+			    unsigned int srcx,
+			    unsigned int srcy,
+			    struct gcrect *dstrect,
+			    int srcangle,
+			    int dstangle,
+			    enum gcscaletype scaletype)
+{
+	enum bverror bverror;
+	struct gccontext *gccontext = get_context();
+	struct gcfilter *gcfilter;
+
+	struct gcmovrdst *gcmovrdst;
+	struct gcmovrsrc *gcmovrsrc;
+	struct gcmostartvr *gcmostartvr;
+
+	struct gcrect srcorig;
+
+	GCENTERARG(GCZONE_FILTER, "scaletype = %d\n", scaletype);
+
+	/* Get a shortcut to the filter properties. */
+	gcfilter = &batch->op.filter;
+
+	/***********************************************************************
+	 * Program the destination.
+	 */
+
+	GCDBG(GCZONE_FILTER, "destination:\n");
+	GCDBG(GCZONE_FILTER, "  angle = %d\n", dstangle);
+	GCDBG(GCZONE_FILTER, "  pixalign = %d,%d\n",
+	      dstinfo->xpixalign, dstinfo->ypixalign);
+	GCDBG(GCZONE_FILTER, "  bytealign = %d\n", dstinfo->bytealign1);
+	GCDBG(GCZONE_FILTER, "  virtstride = %d\n", dstinfo->stride1);
+	GCDBG(GCZONE_FILTER, "  format = %d\n", dstinfo->format.format);
+	GCDBG(GCZONE_FILTER, "  swizzle = %d\n", dstinfo->format.swizzle);
+	GCDBG(GCZONE_FILTER, "  endian = %d\n", dstinfo->format.endian);
+	GCDBG(GCZONE_FILTER, "  premul = %d\n", dstinfo->format.premultiplied);
+	GCDBG(GCZONE_FILTER, "  physwidth = %d\n", dstinfo->physwidth);
+	GCDBG(GCZONE_FILTER, "  physheight = %d\n", dstinfo->physheight);
+	GCPRINT_RECT(GCZONE_FILTER, "  rect", dstrect);
+
+	/* Allocate command buffer. */
+	bverror = claim_buffer(bvbltparams, batch,
+			       sizeof(struct gcmovrdst),
+			       (void **) &gcmovrdst);
+	if (bverror != BVERR_NONE)
+		goto exit;
+
+	/* Add the address fixup. */
+	add_fixup(bvbltparams, batch, &gcmovrdst->address, dstinfo->bytealign1);
+
+	/* Set surface parameters. */
+	gcmovrdst->config_ldst = gcmovrdst_config_ldst;
+	gcmovrdst->address = GET_MAP_HANDLE(dstmap);
+	gcmovrdst->stride = dstinfo->stride1;
+	gcmovrdst->config.raw = 0;
+	gcmovrdst->config.reg.swizzle = dstinfo->format.swizzle;
+	gcmovrdst->config.reg.format = dstinfo->format.format;
+	gcmovrdst->config.reg.endian = dstinfo->format.endian;
+
+	/* Set surface width and height. */
+	gcmovrdst->rotation.raw = 0;
+	gcmovrdst->rotation.reg.surf_width = dstinfo->physwidth;
+	gcmovrdst->rotationheight_ldst = gcmovrdst_rotationheight_ldst;
+	gcmovrdst->rotationheight.raw = 0;
+	gcmovrdst->rotationheight.reg.height = dstinfo->physheight;
+
+	/***********************************************************************
+	 * Program the source.
+	 */
+
+	/* Determine adjusted source bounding rectangle and origin. */
+	srcorig = srcinfo->rect.orig;
+	srcorig.left  -=  srcinfo->xpixalign;
+	srcorig.right -=  srcinfo->xpixalign;
+	srcx          -= (srcinfo->xpixalign << 16);
+
+	GCDBG(GCZONE_FILTER, "source:\n");
+	GCDBG(GCZONE_FILTER, "  angle = %d\n", srcangle);
+	GCDBG(GCZONE_FILTER, "  pixalign = %d,%d\n",
+	      srcinfo->xpixalign, srcinfo->ypixalign);
+	GCDBG(GCZONE_FILTER, "  bytealign = %d\n", srcinfo->bytealign1);
+	GCDBG(GCZONE_FILTER, "  virtstride = %d\n", srcinfo->stride1);
+	GCDBG(GCZONE_FILTER, "  format = %d\n", srcinfo->format.format);
+	GCDBG(GCZONE_FILTER, "  swizzle = %d\n", srcinfo->format.swizzle);
+	GCDBG(GCZONE_FILTER, "  endian = %d\n", srcinfo->format.endian);
+	GCDBG(GCZONE_FILTER, "  premul = %d\n", srcinfo->format.premultiplied);
+	GCDBG(GCZONE_FILTER, "  physwidth = %d\n", srcinfo->physwidth);
+	GCDBG(GCZONE_FILTER, "  physheight = %d\n", srcinfo->physheight);
+	GCPRINT_RECT(GCZONE_FILTER, "  rect", &srcorig);
+
+	GCDBG(GCZONE_FILTER, "src origin: 0x%08X,0x%08X\n", srcx, srcy);
+
+	/* Allocate command buffer. */
+	bverror = claim_buffer(bvbltparams, batch,
+			       sizeof(struct gcmovrsrc),
+			       (void **) &gcmovrsrc);
+	if (bverror != BVERR_NONE)
+		goto exit;
+
+	add_fixup(bvbltparams, batch, &gcmovrsrc->address, srcinfo->bytealign1);
+
+	gcmovrsrc->config_ldst = gcmovrsrc_config_ldst;
+
+	gcmovrsrc->address = GET_MAP_HANDLE(srcmap);
+	gcmovrsrc->stride = srcinfo->stride1;
+
+	gcmovrsrc->rotation.raw = 0;
+	gcmovrsrc->rotation.reg.surf_width = srcinfo->physwidth;
+
+	gcmovrsrc->config.raw = 0;
+	gcmovrsrc->config.reg.swizzle = srcinfo->format.swizzle;
+	gcmovrsrc->config.reg.format = srcinfo->format.format;
+	gcmovrsrc->config.reg.endian = srcinfo->format.endian;
+
+	if (gccontext->gccaps.l2cachefor420 &&
+	    (srcinfo->format.type == BVFMT_YUV) &&
+	    (srcinfo->format.cs.yuv.planecount > 1) &&
+	    ((srcinfo->angle & 1) != 0))
+		gcmovrsrc->config.reg.disable420L2cache
+			= GCREG_SRC_CONFIG_DISABLE420_L2_CACHE_DISABLED;
+
+	gcmovrsrc->pos_ldst = gcmovrsrc_pos_ldst;
+
+	/* Source image bounding box. */
+	gcmovrsrc->lt.reg.left = srcorig.left;
+	gcmovrsrc->lt.reg.top = srcorig.top;
+	gcmovrsrc->rb.reg.right = srcorig.right;
+	gcmovrsrc->rb.reg.bottom = srcorig.bottom;
+
+	/* Fractional origin. */
+	gcmovrsrc->x = srcx;
+	gcmovrsrc->y = srcy;
+
+	/* Program rotation. */
+	gcmovrsrc->rotation_ldst = gcmovrsrc_rotation_ldst;
+	gcmovrsrc->rotationheight.reg.height = srcinfo->physheight;
+	gcmovrsrc->rotationangle.raw = 0;
+	gcmovrsrc->rotationangle.reg.src = rotencoding[srcangle];
+	gcmovrsrc->rotationangle.reg.dst = rotencoding[dstangle];
+	gcmovrsrc->rotationangle.reg.src_mirror = srcinfo->mirror;
+	gcmovrsrc->rotationangle.reg.dst_mirror = dstinfo->mirror;
+
+	gcmovrsrc->rop_ldst = gcmovrsrc_rop_ldst;
+	gcmovrsrc->rop.raw = 0;
+	gcmovrsrc->rop.reg.type = GCREG_ROP_TYPE_ROP3;
+	gcmovrsrc->rop.reg.fg = 0xCC;
+
+	/* Program multiply modes. */
+	gcmovrsrc->mult_ldst = gcmovrsrc_mult_ldst;
+	gcmovrsrc->mult.raw = 0;
+	gcmovrsrc->mult.reg.srcglobalpremul = srcinfo->srcglobalpremul;
+
+	if (srcinfo->format.premultiplied)
+		gcmovrsrc->mult.reg.srcpremul
+		= GCREG_COLOR_MULTIPLY_MODES_SRC_PREMULTIPLY_DISABLE;
+	else
+		gcmovrsrc->mult.reg.srcpremul
+		= GCREG_COLOR_MULTIPLY_MODES_SRC_PREMULTIPLY_ENABLE;
+
+	if (dstinfo->format.premultiplied) {
+		gcmovrsrc->mult.reg.dstpremul
+		= GCREG_COLOR_MULTIPLY_MODES_SRC_PREMULTIPLY_DISABLE;
+
+		gcmovrsrc->mult.reg.dstdemul
+		= GCREG_COLOR_MULTIPLY_MODES_DST_DEMULTIPLY_DISABLE;
+	} else {
+		gcmovrsrc->mult.reg.dstpremul
+		= GCREG_COLOR_MULTIPLY_MODES_SRC_PREMULTIPLY_ENABLE;
+
+		gcmovrsrc->mult.reg.dstdemul
+		= GCREG_COLOR_MULTIPLY_MODES_DST_DEMULTIPLY_ENABLE;
+	}
+
+	/* Program YUV source. */
+	if (srcinfo->format.type == BVFMT_YUV) {
+		bverror = set_yuvsrc(bvbltparams, batch, srcinfo, srcmap);
+		if (bverror != BVERR_NONE)
+			goto exit;
+	}
+
+	/***********************************************************************
+	 * Program blending.
+	 */
+
+	bverror = set_blending(bvbltparams, batch, srcinfo);
+	if (bverror != BVERR_NONE)
+		goto exit;
+
+	/***********************************************************************
+	 * Start the operation.
+	 */
+
+	bverror = claim_buffer(bvbltparams, batch,
+			       sizeof(struct gcmostartvr),
+			       (void **) &gcmostartvr);
+	if (bverror != BVERR_NONE)
+		goto exit;
+
+	switch (scaletype) {
+	case GC_SCALE_OPF:
+		gcmostartvr->scalex = gcfilter->horscalefactor;
+		gcmostartvr->scaley = gcfilter->verscalefactor;
+		gcmostartvr->config = gcregvrconfig_onepass;
+		break;
+
+	case GC_SCALE_HOR:
+		gcmostartvr->scalex = gcfilter->horscalefactor;
+		gcmostartvr->scaley = 0;
+		gcmostartvr->config = gcregvrconfig_horizontal;
+		break;
+
+	case GC_SCALE_VER:
+		gcmostartvr->scalex = 0;
+		gcmostartvr->scaley = gcfilter->verscalefactor;
+		gcmostartvr->config = gcregvrconfig_vertical;
+		break;
+
+	case GC_SCALE_HOR_FLIPPED:
+		gcmostartvr->scalex = 0;
+		gcmostartvr->scaley = gcfilter->horscalefactor;
+		gcmostartvr->config = gcregvrconfig_vertical;
+		break;
+
+	case GC_SCALE_VER_FLIPPED:
+		gcmostartvr->scalex = gcfilter->verscalefactor;
+		gcmostartvr->scaley = 0;
+		gcmostartvr->config = gcregvrconfig_horizontal;
+		break;
+	}
+
+	gcmostartvr->scale_ldst = gcmostartvr_scale_ldst;
+	gcmostartvr->rect_ldst = gcmostartvr_rect_ldst;
+	gcmostartvr->config_ldst = gcmostartvr_config_ldst;
+
+	gcmostartvr->lt.left = dstrect->left;
+	gcmostartvr->lt.top = dstrect->top;
+	gcmostartvr->rb.right = dstrect->right;
+	gcmostartvr->rb.bottom = dstrect->bottom;
+
+exit:
+	GCEXITARG(GCZONE_FILTER, "bv%s = %d\n",
+		  (bverror == BVERR_NONE) ? "result" : "error", bverror);
+	return bverror;
+}
+
+
+/*******************************************************************************
+ * Main fiter entry.
+ */
+
+enum bverror do_filter(struct bvbltparams *bvbltparams,
+		       struct gcbatch *batch,
+		       struct gcsurface *srcinfo)
+{
+	enum bverror bverror = BVERR_NONE;
+	struct gccontext *gccontext = get_context();
+
+	struct gcfilter *gcfilter;
+	struct gcsurface *dstinfo;
+
+	bool scalex, scaley;
+	bool singlepass, twopass;
+
+	struct gcrect *tmporig;
+	struct gcrect *srcorig, *srcclip;
+	struct gcrect *dstorig, *dstclip, *dstadj;
+
+	struct gcrect dstdelta;
+	struct gcrect srcdelta;
+
+	struct bvbuffmap *srcmap = NULL;
+	struct bvbuffmap *tmpmap = NULL;
+	struct bvbuffmap *dstmap = NULL;
+
+	struct gcmovrconfigex *gcmovrconfigex;
+
+	unsigned int srcx, srcy;
+	unsigned int srcwidth, srcheight;
+	unsigned int dstwidth, dstheight;
+	unsigned int horscalefactor, verscalefactor;
+	unsigned int kernelsize;
+	int angle;
+
+	GCENTER(GCZONE_FILTER);
+
+	/* Get some shortcuts. */
+	dstinfo = &batch->dstinfo;
+	gcfilter = &batch->op.filter;
+
+	/* Finish previous batch if any. */
+	bverror = batch->batchend(bvbltparams, batch);
+	if (bverror != BVERR_NONE)
+		goto exit;
+
+	/* ROP is not supported by the filters. */
+	if ((srcinfo->rop & 0xFF) != 0xCC) {
+		BVSETBLTERROR(BVERR_ROP,
+			      "only copy ROP is supported in scaling mode");
+		goto exit;
+	}
+
+	/* Zero-fill for source is not supported. */
+	if (srcinfo->format.zerofill) {
+		BVSETBLTERROR((srcinfo->index == 0)
+					? BVERR_SRC1GEOM_FORMAT
+					: BVERR_SRC2GEOM_FORMAT,
+			      "0 filling is not supported.");
+		goto exit;
+	}
+
+	/* Parse the scale mode. */
+	bverror = parse_scalemode(bvbltparams, batch);
+	if (bverror != BVERR_NONE)
+		goto exit;
+
+	/* Parse destination parameters. */
+	bverror = parse_destination(bvbltparams, batch);
+	if (bverror != BVERR_NONE)
+		goto exit;
+
+	/* Ignore the blit if destination rectangle is empty. */
+	if (null_rect(&dstinfo->rect.clip)) {
+		GCDBG(GCZONE_DEST, "empty destination rectangle.\n");
+		goto exit;
+	}
+
+	/* Get rectangle shortcuts. */
+	srcorig = &srcinfo->rect.orig;
+	srcclip = &srcinfo->rect.clip;
+
+	if ((srcinfo->index == 1) && dstinfo->haveaux) {
+		GCDBG(GCZONE_FILTER, "picking aux set");
+		dstorig = &dstinfo->auxrect.orig;
+		dstclip = &dstinfo->auxrect.clip;
+		dstadj = &dstinfo->auxrect.adj;
+	} else {
+		GCDBG(GCZONE_FILTER, "picking main set");
+		dstorig = &dstinfo->rect.orig;
+		dstclip = &dstinfo->rect.clip;
+		dstadj = &dstinfo->rect.adj;
+	}
+
+	GCPRINT_RECT(GCZONE_FILTER, "original src", srcorig);
+	GCPRINT_RECT(GCZONE_FILTER, "original dst", dstorig);
+	GCPRINT_RECT(GCZONE_FILTER, "clipped dst", dstclip);
+	GCPRINT_RECT(GCZONE_FILTER, "adjusted dst", dstadj);
+
+	/* Compute the source alignments needed to compensate
+	 * for the surface base address misalignment if any. */
+	srcinfo->xpixalign = get_pixel_offset(srcinfo, 0);
+	srcinfo->ypixalign = 0;
+	srcinfo->bytealign1 = (srcinfo->xpixalign
+			    * (int) srcinfo->format.bitspp) / 8;
+	GCDBG(GCZONE_SRC, "source surface offset (pixels) = %d,%d\n",
+		srcinfo->xpixalign, srcinfo->ypixalign);
+	GCDBG(GCZONE_SRC, "source surface offset (bytes) = %d\n",
+		srcinfo->bytealign1);
+
+	/* Determine physical size. */
+	if ((srcinfo->angle % 2) == 0) {
+		srcinfo->physwidth  = srcinfo->width
+				    - srcinfo->xpixalign;
+		srcinfo->physheight = srcinfo->height
+				    - srcinfo->ypixalign;
+	} else {
+		srcinfo->physwidth  = srcinfo->height
+				    - srcinfo->xpixalign;
+		srcinfo->physheight = srcinfo->width
+				    - srcinfo->ypixalign;
+	}
+	GCDBG(GCZONE_SRC, "source physical size = %dx%d\n",
+	      srcinfo->physwidth, srcinfo->physheight);
+
+	/* OPF does not support source rotation, which can be compensated by
+	 * using destination rotation. Compute the adjustment angle.
+	 * For simplicity use the same algorythm for both OPF and TPF. */
+	srcinfo->adjangle = (4 - srcinfo->angle) % 4;
+	adjust_angle(srcinfo, dstinfo);
+
+	/* Set rotation angle. */
+	angle = dstinfo->angle;
+
+	/* Compute U/V plane offsets. */
+	if ((srcinfo->format.type == BVFMT_YUV) &&
+	    (srcinfo->format.cs.yuv.planecount > 1))
+		set_computeyuv(srcinfo, 0, 0);
+
+	/* Determine the source and destination rectangles. */
+	srcwidth  = srcorig->right  - srcorig->left;
+	srcheight = srcorig->bottom - srcorig->top;
+	dstwidth  = dstorig->right  - dstorig->left;
+	dstheight = dstorig->bottom - dstorig->top;
+
+	GCDBG(GCZONE_FILTER, "adjusted input src size: %dx%d\n",
+	      srcwidth, srcheight);
+	GCDBG(GCZONE_FILTER, "adjusted input dst size: %dx%d\n",
+	      dstwidth, dstheight);
+
+	/* Determine the data path. */
+	scalex = (srcwidth  != dstwidth);
+	scaley = (srcheight != dstheight);
+
+	twopass = scalex && scaley;
+	if (twopass) {
+		if (((gcfilter->horkernelsize == 3) ||
+		     (gcfilter->horkernelsize == 5)) &&
+		    ((gcfilter->verkernelsize == 3) ||
+		     (gcfilter->verkernelsize == 5))) {
+			singlepass = true;
+			twopass = false;
+		} else {
+			singlepass = false;
+		}
+	} else {
+		/* Two pass filter in one pass mode. */
+		if (!scalex && !scaley)
+			GCERR("no scaling needed.\n");
+
+		GCDBG(GCZONE_FILTER, "only %s scaling needed.\n",
+			scalex ? "horizontal" : "vertical");
+
+		singlepass = false;
+	}
+
+	gcbv_debug_scaleblt(scalex, scaley, singlepass);
+
+	/* Compute the scale factors. */
+	gcfilter->horscalefactor =
+	horscalefactor = get_scale_factor(srcwidth, dstwidth);
+	GCDBG(GCZONE_FILTER, "horscalefactor = 0x%08X\n", horscalefactor);
+
+	gcfilter->verscalefactor =
+	verscalefactor = get_scale_factor(srcheight, dstheight);
+	GCDBG(GCZONE_FILTER, "verscalefactor = 0x%08X\n", verscalefactor);
+
+	/* Compute the destination offsets. */
+	dstdelta.left   = dstclip->left   - dstorig->left;
+	dstdelta.top    = dstclip->top    - dstorig->top;
+	dstdelta.right  = dstclip->right  - dstorig->left;
+	dstdelta.bottom = dstclip->bottom - dstorig->top;
+	GCDBG(GCZONE_FILTER, "dst deltas = (%d,%d)-(%d,%d)\n",
+	      dstdelta.left, dstdelta.top, dstdelta.right, dstdelta.bottom);
+
+	/* Compute the source offsets. */
+	srcdelta.left   =  dstdelta.left        * horscalefactor;
+	srcdelta.top    =  dstdelta.top         * verscalefactor;
+	srcdelta.right  = (dstdelta.right  - 1) * horscalefactor + (1 << 16);
+	srcdelta.bottom = (dstdelta.bottom - 1) * verscalefactor + (1 << 16);
+
+	/* Before rendering each destination pixel, the HW will select the
+	 * corresponding source center pixel to apply the kernel around.
+	 * To make this process precise we need to add 0.5 to source initial
+	 * coordinates here; this will make HW pick the next source pixel if
+	 * the fraction is equal or greater then 0.5. */
+	srcdelta.left   += 0x00008000;
+	srcdelta.top    += 0x00008000;
+	srcdelta.right  += 0x00008000;
+	srcdelta.bottom += 0x00008000;
+	GCDBG(GCZONE_FILTER, "src deltas = "
+	      "(0x%08X,0x%08X)-(0x%08X,0x%08X)\n",
+	      srcdelta.left, srcdelta.top, srcdelta.right, srcdelta.bottom);
+	GCDBG(GCZONE_FILTER, "src deltas (int) = (%d,%d)-(%d,%d)\n",
+	      srcdelta.left >> 16, srcdelta.top >> 16,
+	      srcdelta.right >> 16, srcdelta.bottom >> 16);
+
+	/* Determine clipped source rectangle. */
+	srcclip->left   = srcorig->left + (srcdelta.left   >> 16);
+	srcclip->top    = srcorig->top  + (srcdelta.top    >> 16);
+	srcclip->right  = srcorig->left + (srcdelta.right  >> 16);
+	srcclip->bottom = srcorig->top  + (srcdelta.bottom >> 16);
+
+	GCDBG(GCZONE_FILTER, "source:\n");
+	GCDBG(GCZONE_FILTER, "  stride = %d, geom = %dx%d\n",
+	      srcinfo->stride1, srcinfo->width, srcinfo->height);
+	GCDBG(GCZONE_FILTER, "  rotation = %d\n", srcinfo->angle);
+	GCPRINT_RECT(GCZONE_FILTER, "  clipped rect", srcclip);
+
+	GCDBG(GCZONE_FILTER, "destination:\n");
+	GCDBG(GCZONE_FILTER, "  stride = %d, geom size = %dx%d\n",
+	      dstinfo->stride1, dstinfo->width, dstinfo->height);
+	GCDBG(GCZONE_FILTER, "  rotation = %d\n", dstinfo->angle);
+	GCPRINT_RECT(GCZONE_FILTER, "  clipped rect", dstclip);
+
+	/* Validate the source rectangle. */
+	if (!valid_rect(srcinfo, srcclip)) {
+		BVSETBLTERROR((srcinfo->index == 0)
+					? BVERR_SRC1RECT
+					: BVERR_SRC2RECT,
+			      "invalid source rectangle.");
+		goto exit;
+	}
+
+	/* Ignore the blit if source rectangle is empty. */
+	if (null_rect(srcclip)) {
+		GCDBG(GCZONE_SURF, "empty source rectangle.\n");
+		goto exit;
+	}
+
+	/* Map the source. */
+	bverror = do_map(srcinfo->buf.desc, batch, &srcmap);
+	if (bverror != BVERR_NONE) {
+		bvbltparams->errdesc = gccontext->bverrorstr;
+		goto exit;
+	}
+
+	/* Map the destination. */
+	bverror = do_map(dstinfo->buf.desc, batch, &dstmap);
+	if (bverror != BVERR_NONE) {
+		bvbltparams->errdesc = gccontext->bverrorstr;
+		goto exit;
+	}
+
+	/* Do single pass filter if we can. */
+	if (singlepass) {
+		GCDBG(GCZONE_TYPE, "single pass\n");
+
+		/* Determine the kernel size to use. */
+		kernelsize = max(gcfilter->horkernelsize,
+				 gcfilter->verkernelsize);
+
+		/* Set kernel size. */
+		bverror = claim_buffer(bvbltparams, batch,
+				       sizeof(struct gcmovrconfigex),
+				       (void **) &gcmovrconfigex);
+		if (bverror != BVERR_NONE)
+			goto exit;
+
+		gcmovrconfigex->config_ldst = gcmovrconfigex_config_ldst;
+		gcmovrconfigex->config.raw = ~0U;
+		gcmovrconfigex->config.reg.kernelsize = kernelsize;
+		gcmovrconfigex->config.reg.mask_kernelsize
+			= GCREG_VR_CONFIG_EX_MASK_FILTER_TAP_ENABLED;
+
+		/* Setup single pass. */
+		srcx = (srcorig->left << 16) + srcdelta.left;
+		srcy = (srcorig->top  << 16) + srcdelta.top;
+		GCDBG(GCZONE_SRC, "src origin: 0x%08X,0x%08X\n", srcx, srcy);
+
+		/* Load the horizontal filter. */
+		bverror = load_filter(bvbltparams, batch,
+				      GC_FILTER_SYNC,
+				      gcfilter->horkernelsize,
+				      gcfilter->horscalefactor,
+				      srcwidth, dstwidth,
+				      gcmofilterkernel_horizontal_ldst);
+		if (bverror != BVERR_NONE)
+			goto exit;
+
+		/* Load the vertical filter. */
+		bverror = load_filter(bvbltparams, batch,
+				      GC_FILTER_SYNC,
+				      gcfilter->verkernelsize,
+				      gcfilter->verscalefactor,
+				      srcheight, dstheight,
+				      gcmofilterkernel_vertical_ldst);
+		if (bverror != BVERR_NONE)
+			goto exit;
+
+		/* Start the operation. */
+		bverror = startvr(bvbltparams, batch,
+				  srcmap, dstmap, srcinfo, dstinfo,
+				  srcx, srcy, dstadj,
+				  ROT_ANGLE_0, angle,
+				  GC_SCALE_OPF);
+	} else if (twopass) {
+		unsigned int horkernelhalf;
+		unsigned int leftextra, rightextra;
+		unsigned int tmprectwidth, tmprectheight;
+		unsigned int tmpalignmask, dstalignmask;
+		unsigned int tmpsize;
+		struct gcsurface tmpinfo;
+
+		GCDBG(GCZONE_TYPE, "two pass\n");
+
+		/* Initialize the temporaty surface descriptor. */
+		tmpinfo.index = -1;
+		tmpinfo.angle = angle;
+		tmpinfo.mirror = GCREG_MIRROR_NONE;
+		tmpinfo.rop = 0;
+		GCDBG(GCZONE_FILTER, "tmp angle = %d\n", tmpinfo.angle);
+
+		/* Transfer blending parameters from the source to the
+		 * temporary buffer so that the blending would happen
+		 * on the second pass. */
+		tmpinfo.gca = srcinfo->gca;
+		srcinfo->gca = NULL;
+
+		/* Determine temporary surface format. */
+		if (srcinfo->format.type == BVFMT_YUV) {
+			if (tmpinfo.angle == ROT_ANGLE_0) {
+				GCDBG(GCZONE_FILTER,
+				      "tmp format = 4:2:2\n");
+				parse_format(bvbltparams, OCDFMT_YUYV,
+					     &tmpinfo.format);
+			} else {
+				GCDBG(GCZONE_FILTER,
+				      "tmp format = dst format\n");
+				tmpinfo.format = dstinfo->format;
+			}
+		} else {
+			GCDBG(GCZONE_FILTER,
+			      "tmp format = src format\n");
+			tmpinfo.format = srcinfo->format;
+		}
+
+		/* Determine pixel alignment masks. */
+		tmpalignmask = GC_BITS_PER_CACHELINE
+			     / tmpinfo.format.bitspp - 1;
+		dstalignmask = GC_BITS_PER_CACHELINE
+			     / dstinfo->format.bitspp - 1;
+
+		/* In partial filter blit cases, the vertical pass has to render
+		 * more pixel information to the left and to the right of the
+		 * temporary image so that the next pass has its necessary
+		 * kernel information on the edges of the image. */
+		horkernelhalf = gcfilter->horkernelsize >> 1;
+
+		leftextra  = srcdelta.left >> 16;
+		rightextra = srcwidth - (srcdelta.right >> 16);
+
+		if (leftextra > horkernelhalf)
+			leftextra = horkernelhalf;
+
+		if (rightextra > horkernelhalf)
+			rightextra = horkernelhalf;
+
+		GCDBG(GCZONE_FILTER, "leftextra = %d, rightextra = %d\n",
+		      leftextra, rightextra);
+
+		/* Determine the source origin. */
+		srcx = ((srcorig->left - leftextra) << 16) + srcdelta.left;
+		srcy =  (srcorig->top << 16) + srcdelta.top;
+		GCDBG(GCZONE_SRC, "src origin: 0x%08X,0x%08X\n", srcx, srcy);
+		GCDBG(GCZONE_SRC, "src origin (int): %d,%d\n",
+		      srcx >> 16, srcy >> 16);
+
+		/* Determine the size of the temporary rectangle. */
+		tmprectwidth = leftextra + rightextra
+			     + ((srcdelta.right >> 16) - (srcdelta.left >> 16));
+		tmprectheight = dstadj->bottom - dstadj->top;
+		GCDBG(GCZONE_FILTER, "tmp rect size: %dx%d\n",
+		      tmprectwidth, tmprectheight);
+
+		/* Shortcut to temporary rectangle. */
+		tmporig = &tmpinfo.rect.orig;
+
+		/* Determine the temporary destination coordinates. */
+		switch (angle) {
+		case ROT_ANGLE_0:
+		case ROT_ANGLE_180:
+			tmporig->left   = (srcx >> 16) & tmpalignmask;
+			tmporig->top    = 0;
+			tmporig->right  = tmporig->left + tmprectwidth;
+			tmporig->bottom = tmprectheight;
+
+			tmpinfo.width  = (tmporig->right + tmpalignmask)
+				       & ~tmpalignmask;
+			tmpinfo.height = tmprectheight;
+
+			tmpinfo.physwidth  = tmpinfo.width;
+			tmpinfo.physheight = tmpinfo.height;
+			break;
+
+		case ROT_ANGLE_90:
+			tmporig->left   = 0;
+			tmporig->top    = dstadj->left & dstalignmask;
+			tmporig->right  = tmprectwidth;
+			tmporig->bottom = tmporig->top  + tmprectheight;
+
+			tmpinfo.width  = tmprectwidth;
+			tmpinfo.height = (tmporig->bottom + tmpalignmask)
+				       & ~tmpalignmask;
+
+			tmpinfo.physwidth  = tmpinfo.height;
+			tmpinfo.physheight = tmpinfo.width;
+			break;
+
+		case ROT_ANGLE_270:
+			tmporig->left   = 0;
+			tmporig->right  = tmprectwidth;
+			tmporig->bottom = dstadj->left & dstalignmask;
+
+			tmpinfo.width  = tmprectwidth;
+			tmpinfo.height = (tmporig->bottom + tmprectheight
+				       + tmpalignmask) & ~tmpalignmask;
+
+			tmporig->bottom = tmpinfo.height - tmporig->bottom;
+			tmporig->top    = tmporig->bottom - tmprectheight;
+
+			tmpinfo.physwidth  = tmpinfo.height;
+			tmpinfo.physheight = tmpinfo.width;
+			break;
+		}
+
+		GCPRINT_RECT(GCZONE_DEST, "tmp dest", tmporig);
+		GCDBG(GCZONE_FILTER, "tmp geometry size = %dx%d\n",
+		      tmpinfo.width, tmpinfo.height);
+		GCDBG(GCZONE_FILTER, "tmp physical size = %dx%d\n",
+		      tmpinfo.physwidth, tmpinfo.physheight);
+
+		/* Determine the size of the temporaty surface. */
+		tmpinfo.stride1 = (tmpinfo.physwidth
+				*  tmpinfo.format.bitspp) / 8;
+		tmpsize = tmpinfo.stride1 * tmpinfo.physheight;
+		tmpsize += GC_BYTES_PER_CACHELINE;
+		tmpsize = (tmpsize + ~PAGE_MASK) & PAGE_MASK;
+		GCDBG(GCZONE_FILTER, "tmp stride = %d\n", tmpinfo.stride1);
+		GCDBG(GCZONE_FILTER, "tmp size (bytes) = %d\n", tmpsize);
+
+		/* Allocate the temporary buffer. */
+		bverror = allocate_temp(bvbltparams, tmpsize);
+		if (bverror != BVERR_NONE)
+			goto exit;
+
+		/* Map the temporary buffer. */
+		tmpinfo.buf.desc = gccontext->tmpbuffdesc;
+		bverror = do_map(tmpinfo.buf.desc, batch, &tmpmap);
+		if (bverror != BVERR_NONE) {
+			bvbltparams->errdesc = gccontext->bverrorstr;
+			goto exit;
+		}
+
+		/* Compute the temp buffer alignments needed to compensate
+		 * for the surface base address misalignment if any. */
+		tmpinfo.xpixalign = 0;
+		tmpinfo.ypixalign = 0;
+		tmpinfo.bytealign1 = (get_pixel_offset(&tmpinfo, 0)
+				   * (int) tmpinfo.format.bitspp) / 8;
+		GCDBG(GCZONE_SRC, "tmp offset (pixels) = %d,%d\n",
+			tmpinfo.xpixalign, tmpinfo.ypixalign);
+		GCDBG(GCZONE_SRC, "tmp offset (bytes) = %d\n",
+			tmpinfo.bytealign1);
+
+		/* Load the vertical filter. */
+		bverror = load_filter(bvbltparams, batch,
+				      GC_FILTER_SYNC,
+				      gcfilter->verkernelsize,
+				      gcfilter->verscalefactor,
+				      srcheight, dstheight,
+				      gcmofilterkernel_shared_ldst);
+		if (bverror != BVERR_NONE)
+			goto exit;
+
+		/* Start the operation. */
+		GCDBG(GCZONE_TYPE, "vertical pass\n");
+		bverror = startvr(bvbltparams, batch,
+				  srcmap, tmpmap, srcinfo, &tmpinfo,
+				  srcx, srcy, tmporig,
+				  ROT_ANGLE_0, angle,
+				  GC_SCALE_VER);
+		if (bverror != BVERR_NONE)
+			goto exit;
+
+		/* Rotation is done in the first pass. */
+		tmpinfo.adjangle = (4 - angle) % 4;
+		adjust_angle(&tmpinfo, dstinfo);
+
+		/* Determine the source origin. */
+		switch (angle) {
+		case ROT_ANGLE_0:
+			srcx = ((tmporig->left + leftextra) << 16)
+			     + (srcdelta.left & 0xFFFF);
+			srcy = tmporig->top << 16;
+			break;
+
+		case ROT_ANGLE_90:
+			srcx = tmporig->left << 16;
+			srcy = ((tmporig->top + rightextra) << 16)
+			     + ((~srcdelta.right + 1) & 0xFFFF);
+			break;
+
+		case ROT_ANGLE_180:
+			srcx = ((tmporig->left + rightextra) << 16)
+			     + ((~srcdelta.right + 1) & 0xFFFF);
+			srcy = tmporig->top << 16;
+			break;
+
+		case ROT_ANGLE_270:
+			srcx = tmporig->left << 16;
+			srcy = ((tmporig->top + leftextra) << 16)
+			     + (srcdelta.left & 0xFFFF);
+			break;
+		}
+
+		GCDBG(GCZONE_SRC, "src origin: 0x%08X,0x%08X\n", srcx, srcy);
+
+		/* Load the horizontal filter. */
+		bverror = load_filter(bvbltparams, batch,
+				      GC_FILTER_SYNC,
+				      gcfilter->horkernelsize,
+				      gcfilter->horscalefactor,
+				      srcwidth, dstwidth,
+				      gcmofilterkernel_shared_ldst);
+		if (bverror != BVERR_NONE)
+			goto exit;
+
+		/* Start the operation. */
+		GCDBG(GCZONE_TYPE, "horizontal pass\n");
+		bverror = startvr(bvbltparams, batch,
+				  tmpmap, dstmap, &tmpinfo, dstinfo,
+				  srcx, srcy, dstadj,
+				  ROT_ANGLE_0, ROT_ANGLE_0,
+				  ((angle % 2) == 0)
+					? GC_SCALE_HOR
+					: GC_SCALE_HOR_FLIPPED);
+		if (bverror != BVERR_NONE)
+			goto exit;
+	} else {
+		GCDBG(GCZONE_TYPE, "two pass (%s pass config).\n",
+		      scalex ? "horizontal" : "vertical");
+
+		/* Setup single pass. */
+		srcx = (srcorig->left << 16) + srcdelta.left;
+		srcy = (srcorig->top  << 16) + srcdelta.top;
+		GCDBG(GCZONE_SRC, "src origin: 0x%08X,0x%08X\n", srcx, srcy);
+
+		if (scalex) {
+			/* Load the horizontal filter. */
+			bverror = load_filter(bvbltparams, batch,
+					      GC_FILTER_SYNC,
+					      gcfilter->horkernelsize,
+					      gcfilter->horscalefactor,
+					      srcwidth, dstwidth,
+					      gcmofilterkernel_shared_ldst);
+			if (bverror != BVERR_NONE)
+				goto exit;
+
+			/* Start the operation. */
+			bverror = startvr(bvbltparams, batch,
+					  srcmap, dstmap, srcinfo, dstinfo,
+					  srcx, srcy, dstadj,
+					  ROT_ANGLE_0, angle,
+					  GC_SCALE_HOR);
+			if (bverror != BVERR_NONE)
+				goto exit;
+		} else {
+			/* Load the vertical filter. */
+			bverror = load_filter(bvbltparams, batch,
+					      GC_FILTER_SYNC,
+					      gcfilter->verkernelsize,
+					      gcfilter->verscalefactor,
+					      srcheight, dstheight,
+					      gcmofilterkernel_shared_ldst);
+			if (bverror != BVERR_NONE)
+				goto exit;
+
+			/* Start the operation. */
+			bverror = startvr(bvbltparams, batch,
+					  srcmap, dstmap, srcinfo, dstinfo,
+					  srcx, srcy, dstadj,
+					  ROT_ANGLE_0, angle,
+					  GC_SCALE_VER);
+			if (bverror != BVERR_NONE)
+				goto exit;
+		}
+	}
+
+exit:
+	GCEXITARG(GCZONE_FILTER, "bv%s = %d\n",
+		  (bverror == BVERR_NONE) ? "result" : "error", bverror);
+	return bverror;
+}
diff --git a/drivers/misc/gcx/gcbv/gcmain.c b/drivers/misc/gcx/gcbv/gcmain.c
new file mode 100644
index 0000000..aa8be66
--- /dev/null
+++ b/drivers/misc/gcx/gcbv/gcmain.c
@@ -0,0 +1,264 @@
+/*
+ * gcmain.c
+ *
+ * Copyright (C) 2010-2011 Vivante Corporation.
+ *
+ * This package is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#include "gcbv.h"
+#include <plat/cpu.h>
+#include <plat/omap_hwmod.h>
+
+
+/*******************************************************************************
+ * BLTsville interface exposure.
+ */
+
+static struct bventry ops = {
+	.structsize = sizeof(struct bventry),
+};
+
+static void gcbv_clear(void)
+{
+	ops.bv_map = NULL;
+	ops.bv_unmap = NULL;
+	ops.bv_blt = NULL;
+	ops.bv_cache = NULL;
+}
+
+static void gcbv_assign(void)
+{
+	ops.bv_map = bv_map;
+	ops.bv_unmap = bv_unmap;
+	ops.bv_blt = bv_blt;
+	ops.bv_cache = bv_cache;
+}
+
+void gcbv_init(struct bventry *entry)
+{
+	*entry = ops;
+}
+EXPORT_SYMBOL(gcbv_init);
+
+
+/*******************************************************************************
+ * Convert floating point in 0..1 range to an 8-bit value in range 0..255.
+ */
+
+union gcfp {
+	struct {
+		unsigned int mantissa:23;
+		unsigned int exponent:8;
+		unsigned int sign:1;
+	} comp;
+
+	float value;
+};
+
+unsigned char gcfp2norm8(float value)
+{
+	union gcfp gcfp;
+	int exponent;
+	unsigned int mantissa;
+	int shift;
+
+	/* Get access to components. */
+	gcfp.value = value;
+
+	/* Clamp negatives. */
+	if (gcfp.comp.sign)
+		return 0;
+
+	/* Get unbiased exponent. */
+	exponent = (int) gcfp.comp.exponent - 127;
+
+	/* Clamp if too large. */
+	if (exponent >= 0)
+		return 255;
+
+	/* Clamp if too small. */
+	if (exponent < -8)
+		return 0;
+
+	/* Determine the shift value. */
+	shift = (23 - 8) - exponent;
+
+	/* Compute the mantissa. */
+	mantissa = (gcfp.comp.mantissa | 0x00800000) >> shift;
+
+	/* Normalize. */
+	mantissa = (mantissa * 255) >> 8;
+
+	return (unsigned char) mantissa;
+}
+
+
+/*******************************************************************************
+ * Surface allocation.
+ */
+
+enum bverror allocate_surface(struct bvbuffdesc **bvbuffdesc,
+			      void **buffer,
+			      unsigned int size)
+{
+	enum bverror bverror;
+	struct bvbuffdesc *tempbuffdesc = NULL;
+	void *tempbuff = NULL;
+	unsigned long *temparray = NULL;
+	struct bvphysdesc *tempphysdesc = NULL;
+	unsigned char *pageaddr;
+	unsigned int i;
+
+	/* Allocate surface buffer descriptor. */
+	tempbuffdesc = vmalloc(sizeof(struct bvbuffdesc));
+	if (tempbuffdesc == NULL) {
+		BVSETERROR(BVERR_OOM, "failed to allocate surface");
+		goto exit;
+	}
+
+	/* Initialize buffer descriptor. */
+	tempbuffdesc->structsize = sizeof(struct bvbuffdesc);
+	tempbuffdesc->virtaddr = NULL;
+	tempbuffdesc->length = size;
+	tempbuffdesc->map = NULL;
+	tempbuffdesc->auxtype = BVAT_PHYSDESC;
+	tempbuffdesc->auxptr = NULL;
+
+	/* Allocate the surface. */
+	tempbuff = vmalloc(size);
+	if (tempbuff == NULL) {
+		BVSETERROR(BVERR_OOM, "failed to allocate surface");
+		goto exit;
+	}
+	tempbuffdesc->virtaddr = tempbuff;
+
+	/* Allocate the physical descriptor. */
+	tempphysdesc = vmalloc(sizeof(struct bvphysdesc));
+	if (tempphysdesc == NULL) {
+		BVSETERROR(BVERR_OOM, "failed to allocate surface");
+		goto exit;
+	}
+	tempbuffdesc->auxptr = tempphysdesc;
+
+	/* Initialize physical descriptor. */
+	tempphysdesc->structsize = sizeof(struct bvphysdesc);
+	tempphysdesc->pagesize = PAGE_SIZE;
+	tempphysdesc->pagearray = NULL;
+	tempphysdesc->pagecount = (size + PAGE_SIZE - 1) / PAGE_SIZE;
+	tempphysdesc->pageoffset = 0;
+
+	/* Allocate array of pages. */
+	temparray = vmalloc(tempphysdesc->pagecount * sizeof(unsigned long));
+	if (temparray == NULL) {
+		BVSETERROR(BVERR_OOM, "failed to allocate surface");
+		goto exit;
+	}
+	tempphysdesc->pagearray = temparray;
+
+	/* Initialize the array. */
+	pageaddr = (unsigned char *) tempbuff;
+	for (i = 0; i < tempphysdesc->pagecount; i += 1) {
+		temparray[i] = PFN_PHYS(vmalloc_to_pfn(pageaddr));
+		pageaddr += PAGE_SIZE;
+	}
+
+	/* Set return pointers. */
+	*bvbuffdesc = tempbuffdesc;
+	*buffer = tempbuff;
+	return BVERR_NONE;
+
+exit:
+	free_surface(tempbuffdesc, tempbuff);
+	return bverror;
+}
+
+void free_surface(struct bvbuffdesc *bvbuffdesc,
+		  void *buffer)
+{
+	if (bvbuffdesc != NULL) {
+		if (bvbuffdesc->virtaddr != NULL)
+			vfree(bvbuffdesc->virtaddr);
+
+		if (bvbuffdesc->auxptr != NULL) {
+			struct bvphysdesc *bvphysdesc;
+
+			bvphysdesc = (struct bvphysdesc *) bvbuffdesc->auxptr;
+			if (bvphysdesc->pagearray != NULL)
+				vfree(bvphysdesc->pagearray);
+
+			vfree(bvphysdesc);
+		}
+
+		vfree(bvbuffdesc);
+	}
+}
+
+
+/*******************************************************************************
+ * Cache operation wrapper.
+ */
+
+enum bverror gcbvcacheop(int count, struct c2dmrgn rgn[],
+			 enum bvcacheop cacheop)
+{
+	enum bverror err = BVERR_NONE;
+
+	switch (cacheop) {
+
+	case DMA_FROM_DEVICE:
+		c2dm_l2cache(count, rgn, cacheop);
+		c2dm_l1cache(count, rgn, cacheop);
+		break;
+
+	case DMA_TO_DEVICE:
+		c2dm_l1cache(count, rgn, cacheop);
+		c2dm_l2cache(count, rgn, cacheop);
+		break;
+
+	case DMA_BIDIRECTIONAL:
+		c2dm_l1cache(count, rgn, cacheop);
+		c2dm_l2cache(count, rgn, cacheop);
+		break;
+
+	default:
+		err = BVERR_CACHEOP;
+		break;
+	}
+
+	return err;
+}
+
+
+/*******************************************************************************
+ * Device init/cleanup.
+ */
+
+static int __init mod_init(void)
+{
+	bv_init();
+
+	/* Assign BV function parameters only if SoC contains a GC core */
+	if (cpu_is_omap447x())
+		gcbv_assign();
+
+	return 0;
+}
+
+static void __exit mod_exit(void)
+{
+	gcbv_clear();
+	bv_exit();
+}
+
+MODULE_LICENSE("GPL v2");
+MODULE_AUTHOR("www.vivantecorp.com");
+MODULE_AUTHOR("www.ti.com");
+module_init(mod_init);
+module_exit(mod_exit);
diff --git a/drivers/misc/gcx/gcbv/gcmain.h b/drivers/misc/gcx/gcbv/gcmain.h
new file mode 100644
index 0000000..8032b32
--- /dev/null
+++ b/drivers/misc/gcx/gcbv/gcmain.h
@@ -0,0 +1,103 @@
+/*
+ * gcmain.h
+ *
+ * Copyright (C) 2010-2011 Vivante Corporation.
+ *
+ * This package is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#ifndef GCMAIN_H
+#define GCMAIN_H
+
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/vmalloc.h>
+#include <linux/dma-mapping.h>
+#include <linux/list.h>
+#include <linux/gcx.h>
+#include <linux/gcioctl.h>
+#include <linux/gccore.h>
+#include <linux/bltsville.h>
+#include <linux/bvinternal.h>
+#include "gcbvdebug.h"
+
+#define GC_DEV_NAME	"gc2d"
+
+
+/*******************************************************************************
+ * Miscellaneous macros.
+ */
+
+#define gcalloc(type, size) \
+	kmalloc(size, GFP_KERNEL)
+
+#define gcfree(ptr) \
+	kfree(ptr)
+
+
+/*******************************************************************************
+ * Core driver API definitions.
+ */
+
+#define gc_getcaps_wrapper(gcicaps) \
+	gc_caps(gcicaps)
+
+#define gc_commit_wrapper(gcicommit) \
+	gc_commit(gcicommit, false)
+
+#define gc_map_wrapper(gcimap) \
+	gc_map(gcimap, false)
+
+#define gc_unmap_wrapper(gcimap) \
+	gc_unmap(gcimap, false)
+
+#define gc_callback_wrapper(gcicallbackarm) \
+	gc_callback(gcicallbackarm, false)
+
+
+/*******************************************************************************
+ * Surface allocation.
+ */
+
+enum bverror allocate_surface(struct bvbuffdesc **bvbuffdesc,
+			      void **buffer,
+			      unsigned int size);
+
+void free_surface(struct bvbuffdesc *bvbuffdesc,
+		  void *buffer);
+
+
+/*******************************************************************************
+ * Floating point conversions.
+ */
+
+unsigned char gcfp2norm8(float value);
+
+
+/*******************************************************************************
+ * Cache operation wrapper.
+ */
+
+enum bverror gcbvcacheop(int count, struct c2dmrgn rgn[],
+			 enum bvcacheop cacheop);
+
+
+/*******************************************************************************
+ * BLTsville API.
+ */
+
+void bv_init(void);
+void bv_exit(void);
+
+enum bverror bv_map(struct bvbuffdesc *buffdesc);
+enum bverror bv_unmap(struct bvbuffdesc *buffdesc);
+enum bverror bv_blt(struct bvbltparams *bltparams);
+enum bverror bv_cache(struct bvcopparams *copparams);
+
+#endif
diff --git a/drivers/misc/gcx/gcbv/gcmap.c b/drivers/misc/gcx/gcbv/gcmap.c
new file mode 100644
index 0000000..6b5fcbe
--- /dev/null
+++ b/drivers/misc/gcx/gcbv/gcmap.c
@@ -0,0 +1,364 @@
+/*
+ * This file is provided under a dual BSD/GPLv2 license.  When using or
+ * redistributing this file, you may do so under either license.
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * Copyright(c) 2012 Vivante Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * BSD LICENSE
+ *
+ * Copyright(c) 2012 Vivante Corporation. 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 Vivante Corporation 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 AND FITNESS FOR A PARTICULAR PURPOSE
+ * 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.
+ */
+
+#include "gcbv.h"
+
+#define GCZONE_NONE		0
+#define GCZONE_ALL		(~0U)
+#define GCZONE_MAPPING		(1 << 0)
+
+GCDBG_FILTERDEF(map, GCZONE_NONE,
+		"mapping")
+
+
+/*******************************************************************************
+ * Memory management.
+ */
+
+enum bverror do_map(struct bvbuffdesc *bvbuffdesc,
+		    struct gcbatch *batch,
+		    struct bvbuffmap **map)
+{
+	static const int mapsize
+		= sizeof(struct bvbuffmap)
+		+ sizeof(struct bvbuffmapinfo);
+
+	enum bverror bverror;
+	struct gccontext *gccontext = get_context();
+	struct bvbuffmap *bvbuffmap;
+	struct bvbuffmapinfo *bvbuffmapinfo;
+	struct bvphysdesc *bvphysdesc;
+	bool mappedbyothers;
+	struct gcimap gcimap;
+	struct gcschedunmap *gcschedunmap;
+
+	GCENTERARG(GCZONE_MAPPING, "bvbuffdesc = 0x%08X\n",
+		   (unsigned int) bvbuffdesc);
+
+	/* Lock access to the mapping list. */
+	GCLOCK(&gccontext->maplock);
+
+	/* Try to find existing mapping. */
+	bvbuffmap = bvbuffdesc->map;
+	while (bvbuffmap != NULL) {
+		if (bvbuffmap->bv_unmap == bv_unmap)
+			break;
+		bvbuffmap = bvbuffmap->nextmap;
+	}
+
+	/* Not mapped yet? */
+	if (bvbuffmap == NULL) {
+		/* New mapping, allocate a record. */
+		if (gccontext->buffmapvac == NULL) {
+			bvbuffmap = gcalloc(struct bvbuffmap, mapsize);
+			if (bvbuffmap == NULL) {
+				BVSETERROR(BVERR_OOM,
+					   "failed to allocate mapping record");
+				goto fail;
+			}
+
+			bvbuffmap->structsize = sizeof(struct bvbuffmap);
+			bvbuffmap->bv_unmap = bv_unmap;
+			bvbuffmap->handle = (unsigned long) (bvbuffmap + 1);
+		} else {
+			bvbuffmap = gccontext->buffmapvac;
+			gccontext->buffmapvac = bvbuffmap->nextmap;
+		}
+
+		/* Setup buffer mapping. Here we need to check and make sure
+		 * that the buffer starts at a location that is supported by
+		 * the hw. If it is not, offset is computed and the buffer is
+		 * extended by the value of the offset. */
+		gcimap.gcerror = GCERR_NONE;
+		gcimap.handle = 0;
+
+		if (bvbuffdesc->auxtype == BVAT_PHYSDESC) {
+			bvphysdesc = (struct bvphysdesc *) bvbuffdesc->auxptr;
+
+			if (bvphysdesc->structsize <
+			    STRUCTSIZE(bvphysdesc, pageoffset)) {
+				BVSETERROR(BVERR_BUFFERDESC_VERS,
+					   "unsupported bvphysdesc version");
+				goto fail;
+			}
+
+			gcimap.buf.offset = bvphysdesc->pageoffset;
+			gcimap.pagesize = bvphysdesc->pagesize;
+			gcimap.pagearray = bvphysdesc->pagearray;
+			gcimap.size = bvbuffdesc->length;
+
+			GCDBG(GCZONE_MAPPING, "new mapping (%s):\n",
+			      (batch == NULL) ? "explicit" : "implicit");
+			GCDBG(GCZONE_MAPPING, "pagesize = %lu\n",
+			      bvphysdesc->pagesize);
+			GCDBG(GCZONE_MAPPING, "pagearray = 0x%08X\n",
+			      (unsigned int) bvphysdesc->pagearray);
+			GCDBG(GCZONE_MAPPING, "pageoffset = %lu\n",
+			      bvphysdesc->pageoffset);
+			GCDBG(GCZONE_MAPPING, "mapping size = %d\n",
+			      gcimap.size);
+		} else {
+			gcimap.buf.logical = bvbuffdesc->virtaddr;
+			gcimap.pagesize = 0;
+			gcimap.pagearray = NULL;
+			gcimap.size = bvbuffdesc->length;
+
+			GCDBG(GCZONE_MAPPING, "new mapping (%s):\n",
+			      (batch == NULL) ? "explicit" : "implicit");
+			GCDBG(GCZONE_MAPPING, "specified virtaddr = 0x%08X\n",
+			      (unsigned int) bvbuffdesc->virtaddr);
+			GCDBG(GCZONE_MAPPING, "aligned virtaddr = 0x%08X\n",
+			      (unsigned int) gcimap.buf.logical);
+			GCDBG(GCZONE_MAPPING, "mapping size = %d\n",
+			      gcimap.size);
+		}
+
+		gc_map_wrapper(&gcimap);
+		if (gcimap.gcerror != GCERR_NONE) {
+			BVSETERROR(BVERR_OOM,
+				   "unable to allocate gccore memory");
+			goto fail;
+		}
+
+		/* Set map handle. */
+		bvbuffmapinfo = (struct bvbuffmapinfo *) bvbuffmap->handle;
+		bvbuffmapinfo->handle = gcimap.handle;
+
+		/* Initialize reference counters. */
+		if (batch == NULL) {
+			/* Explicit mapping. */
+			bvbuffmapinfo->usermap = 1;
+			bvbuffmapinfo->automap = 0;
+		} else {
+			/* Implicit mapping; if there are existing mappings
+			 * from other implementations, mark this an explicit
+			 * mapping as well. */
+			mappedbyothers = (bvbuffdesc->map != NULL);
+			GCDBG(GCZONE_MAPPING, "%smapped by others.\n",
+			      mappedbyothers ? "" : "not ");
+
+			bvbuffmapinfo->usermap = mappedbyothers ? 1 : 0;
+			bvbuffmapinfo->automap = 1;
+		}
+
+		/* Add the record to the list of mappings. */
+		bvbuffmap->nextmap = bvbuffdesc->map;
+		bvbuffdesc->map = bvbuffmap;
+	} else {
+		/* Mapping already exists. */
+		bvbuffmapinfo = (struct bvbuffmapinfo *) bvbuffmap->handle;
+
+		/* Advance reference counters. */
+		if (batch == NULL) {
+			/* Explicit mapping. */
+			GCDBG(GCZONE_MAPPING, "explicit map.\n");
+			bvbuffmapinfo->usermap += 1;
+		} else {
+			/* Implicit mapping. */
+			GCDBG(GCZONE_MAPPING, "implicit map.\n");
+			bvbuffmapinfo->automap += 1;
+		}
+
+		GCDBG(GCZONE_MAPPING, "mapping exists.\n");
+	}
+
+	GCDBG(GCZONE_MAPPING, "bvbuffmap = 0x%08X\n",
+		(unsigned int) bvbuffmap);
+	GCDBG(GCZONE_MAPPING, "explicit count = %d\n",
+		bvbuffmapinfo->usermap);
+	GCDBG(GCZONE_MAPPING, "implicit count = %d\n",
+		bvbuffmapinfo->automap);
+
+	/* Schedule for unmapping. */
+	if (batch != NULL) {
+		if (list_empty(&gccontext->unmapvac)) {
+			gcschedunmap = gcalloc(struct gcschedunmap,
+					       sizeof(struct gcschedunmap));
+			if (gcschedunmap == NULL) {
+				BVSETERROR(BVERR_OOM,
+					   "failed to schedule unmapping");
+				goto fail;
+			}
+			list_add(&gcschedunmap->link, &batch->unmap);
+		} else {
+			struct list_head *head;
+			head = gccontext->unmapvac.next;
+			gcschedunmap = list_entry(head,
+						  struct gcschedunmap,
+						  link);
+			list_move(&gcschedunmap->link, &batch->unmap);
+		}
+
+		gcschedunmap->handle = (unsigned long) bvbuffdesc;
+
+		GCDBG(GCZONE_MAPPING, "scheduled for unmapping.\n");
+	}
+
+	/* Set the map pointer. */
+	*map = bvbuffmap;
+
+	/* Unlock access to the mapping list. */
+	GCUNLOCK(&gccontext->maplock);
+
+	GCEXITARG(GCZONE_MAPPING, "handle = 0x%08X\n",
+		  bvbuffmapinfo->handle);
+	return BVERR_NONE;
+
+fail:
+	if (bvbuffmap != NULL) {
+		bvbuffmap->nextmap = gccontext->buffmapvac;
+		gccontext->buffmapvac = bvbuffmap;
+	}
+
+	/* Unlock access to the mapping list. */
+	GCUNLOCK(&gccontext->maplock);
+
+	GCEXITARG(GCZONE_MAPPING, "bverror = %d\n", bverror);
+	return bverror;
+}
+
+void do_unmap_implicit(struct gcbatch *batch)
+{
+	struct gccontext *gccontext = get_context();
+	struct list_head *head, *temphead;
+	struct gcschedunmap *gcschedunmap;
+	struct bvbuffdesc *bvbuffdesc;
+	struct bvbuffmap *prev, *bvbuffmap;
+	struct bvbuffmapinfo *bvbuffmapinfo;
+
+	GCENTER(GCZONE_MAPPING);
+
+	/* Lock access to the mapping list. */
+	GCLOCK(&gccontext->maplock);
+
+	/* Scan scheduled unmappings and remove the ones that are still
+	 * in use. */
+	list_for_each_safe(head, temphead, &batch->unmap) {
+		gcschedunmap = list_entry(head, struct gcschedunmap, link);
+
+		/* Cast the handle. */
+		bvbuffdesc = (struct bvbuffdesc *) gcschedunmap->handle;
+
+		/* Find our mapping. */
+		prev = NULL;
+		bvbuffmap = bvbuffdesc->map;
+		while (bvbuffmap != NULL) {
+			if (bvbuffmap->bv_unmap == bv_unmap)
+				break;
+			prev = bvbuffmap;
+			bvbuffmap = bvbuffmap->nextmap;
+		}
+
+		/* Not found? */
+		if (bvbuffmap == NULL) {
+			GCERR("mapping not found for bvbuffdesc 0x%08X.\n",
+			      (unsigned int) bvbuffdesc);
+
+			/* Remove scheduled unmapping. */
+			list_move(head, &gccontext->unmapvac);
+			continue;
+		}
+
+		/* Get the info structure. */
+		bvbuffmapinfo = (struct bvbuffmapinfo *) bvbuffmap->handle;
+
+		GCDBG(GCZONE_MAPPING, "head = 0x%08X\n",
+		      (unsigned int) gcschedunmap);
+		GCDBG(GCZONE_MAPPING, "  bvbuffmap = 0x%08X\n",
+		      (unsigned int) bvbuffmap);
+		GCDBG(GCZONE_MAPPING, "  handle = 0x%08X\n",
+		      bvbuffmapinfo->handle);
+
+		/* Implicit unmapping. */
+		bvbuffmapinfo->automap -= 1;
+		if (bvbuffmapinfo->automap < 0) {
+			GCERR("implicit count negative.\n");
+			bvbuffmapinfo->automap = 0;
+		}
+
+		GCDBG(GCZONE_MAPPING, "  explicit count = %d\n",
+		      bvbuffmapinfo->usermap);
+		GCDBG(GCZONE_MAPPING, "  implicit count = %d\n",
+		      bvbuffmapinfo->automap);
+
+		/* Still referenced? */
+		if (bvbuffmapinfo->usermap || bvbuffmapinfo->automap) {
+			GCDBG(GCZONE_MAPPING, "  still referenced.\n");
+
+			/* Remove scheduled unmapping. */
+			list_move(head, &gccontext->unmapvac);
+			continue;
+		}
+
+		GCDBG(GCZONE_MAPPING, "  ready for unmapping.\n");
+
+		/* Set the handle. */
+		gcschedunmap->handle = bvbuffmapinfo->handle;
+
+		/* Remove from the buffer descriptor. */
+		if (prev == NULL)
+			bvbuffdesc->map = bvbuffmap->nextmap;
+		else
+			prev->nextmap = bvbuffmap->nextmap;
+
+		/* Add to the vacant list. */
+		bvbuffmap->nextmap = gccontext->buffmapvac;
+		gccontext->buffmapvac = bvbuffmap;
+	}
+
+	/* Unlock access to the mapping list. */
+	GCUNLOCK(&gccontext->maplock);
+
+	GCEXIT(GCZONE_MAPPING);
+}
diff --git a/drivers/misc/gcx/gcbv/gcparser.c b/drivers/misc/gcx/gcbv/gcparser.c
new file mode 100644
index 0000000..b90d398
--- /dev/null
+++ b/drivers/misc/gcx/gcbv/gcparser.c
@@ -0,0 +1,2416 @@
+/*
+ * This file is provided under a dual BSD/GPLv2 license.  When using or
+ * redistributing this file, you may do so under either license.
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * Copyright(c) 2012 Vivante Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * BSD LICENSE
+ *
+ * Copyright(c) 2012 Vivante Corporation. 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 Vivante Corporation 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 AND FITNESS FOR A PARTICULAR PURPOSE
+ * 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.
+ */
+
+#include "gcbv.h"
+
+#define GCZONE_NONE		0
+#define GCZONE_ALL		(~0U)
+#define GCZONE_FORMAT		(1 << 0)
+#define GCZONE_FORMAT_VERBOSE	(1 << 1)
+#define GCZONE_BLEND		(1 << 2)
+#define GCZONE_OFFSET		(1 << 3)
+#define GCZONE_DEST		(1 << 4)
+#define GCZONE_SRC		(1 << 5)
+#define GCZONE_SCALING		(1 << 6)
+#define GCZONE_SURF		(1 << 7)
+
+GCDBG_FILTERDEF(parser, GCZONE_NONE,
+		"format",
+		"formatverbose",
+		"blend",
+		"offset",
+		"dest",
+		"src",
+		"scaling",
+		"surface")
+
+
+/*******************************************************************************
+ * Internal macros.
+ */
+
+#define GCCONVERT_RECT(zone, name, bvrect, gcrect) \
+{ \
+	(gcrect)->left = (bvrect)->left; \
+	(gcrect)->top = (bvrect)->top; \
+	(gcrect)->right = (bvrect)->left + (bvrect)->width; \
+	(gcrect)->bottom = (bvrect)->top + (bvrect)->height; \
+	\
+	GCPRINT_RECT(zone, name, gcrect); \
+}
+
+
+/*******************************************************************************
+ * Pixel format parser.
+ */
+
+#define OCDFMTDEF_PLACEMENT_SHIFT 9
+#define OCDFMTDEF_PLACEMENT_MASK (3 << OCDFMTDEF_PLACEMENT_SHIFT)
+
+#define BVCOMP(Shift, Size) \
+	{ Shift, Size, ((1 << Size) - 1) << Shift }
+
+#define BVRED(Shift, Size) \
+	BVCOMP(Shift, Size)
+
+#define BVGREEN(Shift, Size) \
+	BVCOMP(Shift, Size)
+
+#define BVBLUE(Shift, Size) \
+	BVCOMP(Shift, Size)
+
+#define BVALPHA(Shift, Size) \
+	BVCOMP(Shift, Size)
+
+static const unsigned int rgba16swizzle[] = {
+	GCREG_DE_SWIZZLE_ARGB,
+	GCREG_DE_SWIZZLE_RGBA,
+	GCREG_DE_SWIZZLE_ABGR,
+	GCREG_DE_SWIZZLE_BGRA
+};
+
+static const unsigned int rgb16swizzle[] = {
+	GCREG_DE_SWIZZLE_ARGB,
+	GCREG_DE_SWIZZLE_ARGB,
+	GCREG_DE_SWIZZLE_ABGR,
+	GCREG_DE_SWIZZLE_ABGR
+};
+
+static const unsigned int rgba32swizzle[] = {
+	GCREG_DE_SWIZZLE_ARGB,
+	GCREG_DE_SWIZZLE_ABGR,
+	GCREG_DE_SWIZZLE_ABGR,
+	GCREG_DE_SWIZZLE_ARGB
+};
+
+static const struct bvcsrgb xrgb4444_bits[] = {
+	{ BVRED(8,  4), BVGREEN(4, 4), BVBLUE(0,  4), BVALPHA(12, 0) },
+	{ BVRED(12, 4), BVGREEN(8, 4), BVBLUE(4,  4), BVALPHA(0,  0) },
+	{ BVRED(0,  4), BVGREEN(4, 4), BVBLUE(8,  4), BVALPHA(12, 0) },
+	{ BVRED(4,  4), BVGREEN(8, 4), BVBLUE(12, 4), BVALPHA(0,  0) }
+};
+
+static const struct bvcsrgb argb4444_bits[] = {
+	{ BVRED(8,  4), BVGREEN(4, 4), BVBLUE(0,  4), BVALPHA(12, 4) },
+	{ BVRED(12, 4), BVGREEN(8, 4), BVBLUE(4,  4), BVALPHA(0,  4) },
+	{ BVRED(0,  4), BVGREEN(4, 4), BVBLUE(8,  4), BVALPHA(12, 4) },
+	{ BVRED(4,  4), BVGREEN(8, 4), BVBLUE(12, 4), BVALPHA(0,  4) }
+};
+
+static const struct bvcsrgb xrgb1555_bits[] = {
+	{ BVRED(10, 5), BVGREEN(5, 5), BVBLUE(0,  5), BVALPHA(15, 0) },
+	{ BVRED(11, 5), BVGREEN(6, 5), BVBLUE(1,  5), BVALPHA(0,  0) },
+	{ BVRED(0,  5), BVGREEN(5, 5), BVBLUE(10, 5), BVALPHA(15, 0) },
+	{ BVRED(1,  5), BVGREEN(6, 5), BVBLUE(11, 5), BVALPHA(0,  0) }
+};
+
+static const struct bvcsrgb argb1555_bits[] = {
+	{ BVRED(10, 5), BVGREEN(5, 5), BVBLUE(0,  5), BVALPHA(15, 1) },
+	{ BVRED(11, 5), BVGREEN(6, 5), BVBLUE(1,  5), BVALPHA(0,  1) },
+	{ BVRED(0,  5), BVGREEN(5, 5), BVBLUE(10, 5), BVALPHA(15, 1) },
+	{ BVRED(1,  5), BVGREEN(6, 5), BVBLUE(11, 5), BVALPHA(0,  1) }
+};
+
+static const struct bvcsrgb rgb565_bits[] = {
+	{ BVRED(11, 5), BVGREEN(5, 6), BVBLUE(0,  5), BVALPHA(0, 0) },
+	{ BVRED(11, 5), BVGREEN(5, 6), BVBLUE(0,  5), BVALPHA(0, 0) },
+	{ BVRED(0,  5), BVGREEN(5, 6), BVBLUE(11, 5), BVALPHA(0, 0) },
+	{ BVRED(0,  5), BVGREEN(5, 6), BVBLUE(11, 5), BVALPHA(0, 0) }
+};
+
+static const struct bvcsrgb xrgb8888_bits[] = {
+	{ BVRED(8,  8), BVGREEN(16, 8), BVBLUE(24, 8), BVALPHA(0,  0) },
+	{ BVRED(0,  8), BVGREEN(8,  8), BVBLUE(16, 8), BVALPHA(24, 0) },
+	{ BVRED(24, 8), BVGREEN(16, 8), BVBLUE(8,  8), BVALPHA(0,  0) },
+	{ BVRED(16, 8), BVGREEN(8,  8), BVBLUE(0,  8), BVALPHA(24, 0) }
+};
+
+static const struct bvcsrgb argb8888_bits[] = {
+	{ BVRED(8,  8), BVGREEN(16, 8), BVBLUE(24, 8), BVALPHA(0,  8) },
+	{ BVRED(0,  8), BVGREEN(8,  8), BVBLUE(16, 8), BVALPHA(24, 8) },
+	{ BVRED(24, 8), BVGREEN(16, 8), BVBLUE(8,  8), BVALPHA(0,  8) },
+	{ BVRED(16, 8), BVGREEN(8,  8), BVBLUE(0,  8), BVALPHA(24, 8) }
+};
+
+static const unsigned int container[] = {
+	  8,	/* OCDFMTDEF_CONTAINER_8BIT */
+	 16,	/* OCDFMTDEF_CONTAINER_16BIT */
+	 24,	/* OCDFMTDEF_CONTAINER_24BIT */
+	 32,	/* OCDFMTDEF_CONTAINER_32BIT */
+	~0U,	/* reserved */
+	 48,	/* OCDFMTDEF_CONTAINER_48BIT */
+	~0U,	/* reserved */
+	 64	/* OCDFMTDEF_CONTAINER_64BIT */
+};
+
+enum bverror parse_format(struct bvbltparams *bvbltparams,
+			  enum ocdformat ocdformat,
+			  struct bvformatxlate *format)
+{
+	enum bverror bverror = BVERR_NONE;
+	struct gccontext *gccontext = get_context();
+	unsigned int cs, std, alpha, subsample, layout;
+	unsigned int reversed, leftjust, swizzle, cont, bits;
+
+	GCENTERARG(GCZONE_FORMAT, "ocdformat = 0x%08X\n", ocdformat);
+
+	cs = (ocdformat & OCDFMTDEF_CS_MASK)
+		>> OCDFMTDEF_CS_SHIFT;
+	std = (ocdformat & OCDFMTDEF_STD_MASK)
+		>> OCDFMTDEF_STD_SHIFT;
+	alpha = ocdformat & OCDFMTDEF_ALPHA;
+	subsample = (ocdformat & OCDFMTDEF_SUBSAMPLE_MASK)
+		>> OCDFMTDEF_SUBSAMPLE_SHIFT;
+	layout = (ocdformat & OCDFMTDEF_LAYOUT_MASK)
+		>> OCDFMTDEF_LAYOUT_SHIFT;
+	cont = (ocdformat & OCDFMTDEF_CONTAINER_MASK)
+		>> OCDFMTDEF_CONTAINER_SHIFT;
+	bits = ((ocdformat & OCDFMTDEF_COMPONENTSIZEMINUS1_MASK)
+		>> OCDFMTDEF_COMPONENTSIZEMINUS1_SHIFT) + 1;
+
+	GCDBG(GCZONE_FORMAT_VERBOSE, "std = %d\n", std);
+	GCDBG(GCZONE_FORMAT_VERBOSE, "cs = %d\n", cs);
+	GCDBG(GCZONE_FORMAT_VERBOSE, "alpha = %d\n", alpha ? 1 : 0);
+	GCDBG(GCZONE_FORMAT_VERBOSE, "subsample = %d\n", subsample);
+	GCDBG(GCZONE_FORMAT_VERBOSE, "layout = %d\n", layout);
+	GCDBG(GCZONE_FORMAT_VERBOSE, "cont = %d\n", cont);
+	GCDBG(GCZONE_FORMAT_VERBOSE, "bits = %d\n", bits);
+
+	format->endian
+		= GCREG_DEST_CONFIG_ENDIAN_CONTROL_NO_SWAP;
+
+	switch (cs) {
+	case (OCDFMTDEF_CS_RGB >> OCDFMTDEF_CS_SHIFT):
+		GCDBG(GCZONE_FORMAT, "OCDFMTDEF_CS_RGB\n");
+
+		/* Determine the swizzle. */
+		swizzle = (ocdformat & OCDFMTDEF_PLACEMENT_MASK)
+			>> OCDFMTDEF_PLACEMENT_SHIFT;
+		GCDBG(GCZONE_FORMAT, "swizzle = %d\n", swizzle);
+
+		/* RGB color space. */
+		format->type = BVFMT_RGB;
+
+		/* Has to be 0 for RGB. */
+		if (std != 0) {
+			BVSETBLTERROR(BVERR_UNK,
+				      "unsupported standard");
+			goto exit;
+		}
+
+		/* Determine premultuplied or not. */
+		if (alpha == OCDFMTDEF_ALPHA) {
+			format->premultiplied
+				= ((ocdformat & OCDFMTDEF_NON_PREMULT) == 0);
+			format->zerofill = false;
+		} else {
+			format->premultiplied = true;
+			format->zerofill
+				= ((ocdformat & OCDFMTDEF_FILL_EMPTY_0) != 0);
+		}
+		GCDBG(GCZONE_FORMAT, "premultiplied = %d\n",
+		      format->premultiplied);
+
+		/* No subsample support. */
+		if (subsample !=
+		    (OCDFMTDEF_SUBSAMPLE_NONE >> OCDFMTDEF_SUBSAMPLE_SHIFT)) {
+			BVSETBLTERROR(BVERR_UNK,
+					"subsampling for RGB is not supported");
+			goto exit;
+		}
+
+		/* Only packed RGB is supported. */
+		if (layout !=
+		    (OCDFMTDEF_PACKED >> OCDFMTDEF_LAYOUT_SHIFT)) {
+			BVSETBLTERROR(BVERR_UNK,
+				      "only packed RGBA formats are supported");
+			goto exit;
+		}
+
+		/* Determine the format. */
+		switch (bits) {
+		case 12:
+			format->bitspp = 16;
+			format->allocbitspp = 16;
+			format->swizzle = rgba16swizzle[swizzle];
+
+			if (alpha == OCDFMTDEF_ALPHA) {
+				format->format = GCREG_DE_FORMAT_A4R4G4B4;
+				format->cs.rgb.comp = &argb4444_bits[swizzle];
+			} else {
+				format->format = gccontext->gccaps.swizzlefixed
+					? GCREG_DE_FORMAT_X4R4G4B4
+					: GCREG_DE_FORMAT_A4R4G4B4;
+				format->cs.rgb.comp = &xrgb4444_bits[swizzle];
+			}
+			break;
+
+		case 15:
+			format->bitspp = 16;
+			format->allocbitspp = 16;
+			format->swizzle = rgba16swizzle[swizzle];
+
+			if (alpha == OCDFMTDEF_ALPHA) {
+				format->format = GCREG_DE_FORMAT_A1R5G5B5;
+				format->cs.rgb.comp = &argb1555_bits[swizzle];
+			} else {
+				format->format = GCREG_DE_FORMAT_X1R5G5B5;
+				format->cs.rgb.comp = &xrgb1555_bits[swizzle];
+			}
+			break;
+
+		case 16:
+			if (alpha == OCDFMTDEF_ALPHA) {
+				BVSETBLTERROR(BVERR_UNK,
+					      "alpha component is not supported"
+					      "for this format.");
+				goto exit;
+			}
+
+			format->bitspp = 16;
+			format->allocbitspp = 16;
+			format->swizzle = rgb16swizzle[swizzle];
+			format->format = GCREG_DE_FORMAT_R5G6B5;
+			format->cs.rgb.comp = &rgb565_bits[swizzle];
+			break;
+
+		case 24:
+			format->bitspp = 32;
+			format->allocbitspp = 32;
+			format->swizzle = rgba32swizzle[swizzle];
+
+			if (alpha == OCDFMTDEF_ALPHA) {
+				format->format = GCREG_DE_FORMAT_A8R8G8B8;
+				format->cs.rgb.comp = &argb8888_bits[swizzle];
+			} else {
+				format->format = GCREG_DE_FORMAT_X8R8G8B8;
+				format->cs.rgb.comp = &xrgb8888_bits[swizzle];
+			}
+
+			format->endian = ((swizzle & 1) == 0)
+				? GCREG_DEST_CONFIG_ENDIAN_CONTROL_SWAP_DWORD
+				: GCREG_DEST_CONFIG_ENDIAN_CONTROL_NO_SWAP;
+			break;
+
+		default:
+			BVSETBLTERROR(BVERR_UNK,
+				      "unsupported bit width %d", bits);
+			goto exit;
+		}
+
+		if (format->allocbitspp != container[cont]) {
+			BVSETBLTERROR(BVERR_UNK,
+				      "unsupported container");
+			goto exit;
+		}
+		break;
+
+	case (OCDFMTDEF_CS_YCbCr >> OCDFMTDEF_CS_SHIFT):
+		GCDBG(GCZONE_FORMAT, "OCDFMTDEF_CS_YCbCr\n");
+
+		/* YUV color space. */
+		format->type = BVFMT_YUV;
+
+		/* Determine the swizzle. */
+		reversed = ocdformat & OCDFMTDEF_REVERSED;
+		leftjust = ocdformat & OCDFMTDEF_LEFT_JUSTIFIED;
+		GCDBG(GCZONE_FORMAT_VERBOSE, "reversed = %d\n",
+		      reversed ? 1 : 0);
+		GCDBG(GCZONE_FORMAT_VERBOSE, "leftjust = %d\n",
+		      leftjust ? 1 : 0);
+
+		/* Parse the standard. */
+		switch (std) {
+		case OCDFMTDEF_STD_ITUR_601_YCbCr >> OCDFMTDEF_STD_SHIFT:
+			GCDBG(GCZONE_FORMAT, "OCDFMTDEF_STD_ITUR_601_YCbCr\n");
+			format->cs.yuv.std = GCREG_PE_CONTROL_YUV_601;
+			break;
+
+		case OCDFMTDEF_STD_ITUR_709_YCbCr >> OCDFMTDEF_STD_SHIFT:
+			GCDBG(GCZONE_FORMAT, "OCDFMTDEF_STD_ITUR_709_YCbCr\n");
+			format->cs.yuv.std = GCREG_PE_CONTROL_YUV_709;
+			break;
+
+		default:
+			BVSETBLTERROR(BVERR_UNK,
+				      "unsupported color standard");
+			goto exit;
+		}
+
+		/* Alpha is not supported. */
+		if (alpha == OCDFMTDEF_ALPHA) {
+			BVSETBLTERROR(BVERR_UNK,
+				      "alpha channel is not supported");
+			goto exit;
+		}
+
+		format->premultiplied = true;
+		format->zerofill = false;
+
+		/* Parse subsampling. */
+		switch (subsample) {
+		case OCDFMTDEF_SUBSAMPLE_422_YCbCr >> OCDFMTDEF_SUBSAMPLE_SHIFT:
+			GCDBG(GCZONE_FORMAT, "OCDFMTDEF_SUBSAMPLE_422_YCbCr\n");
+
+			/* Parse layout. */
+			switch (layout) {
+			case OCDFMTDEF_PACKED >> OCDFMTDEF_LAYOUT_SHIFT:
+				GCDBG(GCZONE_FORMAT, "OCDFMTDEF_PACKED\n");
+
+				if (container[cont] != 32) {
+					BVSETBLTERROR(BVERR_UNK,
+						      "unsupported container");
+					goto exit;
+				}
+
+				format->bitspp = 16;
+				format->allocbitspp = 16;
+				format->format = leftjust
+					? GCREG_DE_FORMAT_YUY2
+					: GCREG_DE_FORMAT_UYVY;
+				format->swizzle = reversed
+					? GCREG_PE_CONTROL_UV_SWIZZLE_VU
+					: GCREG_PE_CONTROL_UV_SWIZZLE_UV;
+				format->cs.yuv.planecount = 1;
+				format->cs.yuv.xsample = 2;
+				format->cs.yuv.ysample = 1;
+				break;
+
+			default:
+				BVSETBLTERROR(BVERR_UNK,
+					      "specified 4:2:2 layout "
+					      "is not supported");
+				goto exit;
+			}
+			break;
+
+		case OCDFMTDEF_SUBSAMPLE_420_YCbCr >> OCDFMTDEF_SUBSAMPLE_SHIFT:
+
+			/* Parse layout. */
+			switch (layout) {
+			case OCDFMTDEF_2_PLANE_YCbCr
+						>> OCDFMTDEF_LAYOUT_SHIFT:
+				GCDBG(GCZONE_FORMAT,
+				      "OCDFMTDEF_2_PLANE_YCbCr\n");
+
+				if (container[cont] != 48) {
+					BVSETBLTERROR(BVERR_UNK,
+						      "unsupported container");
+					goto exit;
+				}
+
+				format->bitspp = 8;
+				format->allocbitspp = 12;
+				format->format = GCREG_DE_FORMAT_NV12;
+				format->swizzle = reversed
+					? GCREG_PE_CONTROL_UV_SWIZZLE_VU
+					: GCREG_PE_CONTROL_UV_SWIZZLE_UV;
+				format->cs.yuv.planecount = 2;
+				format->cs.yuv.xsample = 2;
+				format->cs.yuv.ysample = 2;
+				break;
+
+			case OCDFMTDEF_3_PLANE_STACKED
+						>> OCDFMTDEF_LAYOUT_SHIFT:
+				GCDBG(GCZONE_FORMAT,
+				      "OCDFMTDEF_3_PLANE_STACKED\n");
+
+				if (container[cont] != 48) {
+					BVSETBLTERROR(BVERR_UNK,
+						      "unsupported container");
+					goto exit;
+				}
+
+				format->bitspp = 8;
+				format->allocbitspp = 12;
+				format->format = GCREG_DE_FORMAT_YV12;
+				format->swizzle = reversed
+					? GCREG_PE_CONTROL_UV_SWIZZLE_VU
+					: GCREG_PE_CONTROL_UV_SWIZZLE_UV;
+				format->cs.yuv.planecount = 3;
+				format->cs.yuv.xsample = 2;
+				format->cs.yuv.ysample = 2;
+				break;
+
+			default:
+				BVSETBLTERROR(BVERR_UNK,
+					      "specified 4:2:2 layout "
+					      "is not supported");
+				goto exit;
+			}
+			break;
+
+		default:
+			BVSETBLTERROR(BVERR_UNK,
+				      "specified subsampling is not supported");
+			goto exit;
+		}
+
+		if (format->allocbitspp != bits) {
+			BVSETBLTERROR(BVERR_UNK,
+				      "unsupported bit width %d", bits);
+			goto exit;
+		}
+		break;
+
+	default:
+		BVSETBLTERROR(BVERR_UNK,
+			      "unsupported color space %d", cs);
+		goto exit;
+	}
+
+	GCDBG(GCZONE_FORMAT, "bpp = %d\n", format->bitspp);
+	GCDBG(GCZONE_FORMAT, "gcformat = %d\n", format->format);
+	GCDBG(GCZONE_FORMAT, "gcswizzle = %d\n", format->swizzle);
+
+	bverror = BVERR_NONE;
+
+exit:
+	GCEXITARG(GCZONE_FORMAT, "bv%s = %d\n",
+		  (bverror == BVERR_NONE) ? "result" : "error", bverror);
+	return bverror;
+}
+
+
+/*******************************************************************************
+ * Alpha blending parser.
+ */
+
+#define BVBLENDMATCH(Mode, Inverse, Normal) \
+( \
+	BVBLENDDEF_ ## Mode | \
+	BVBLENDDEF_ ## Inverse | \
+	BVBLENDDEF_ ## Normal \
+)
+
+#define BVSRC1USE(Use) \
+	Use
+
+#define BVSRC2USE(Use) \
+	Use
+
+#define BVBLENDUNDEFINED() \
+	{ ~0, ~0, { 0, 0, 0, 0 }, { 0, 0, 0, 0 } }
+
+struct bvblendxlate {
+	unsigned char match1;
+	unsigned char match2;
+
+	struct gcblendconfig k1;
+	struct gcblendconfig k2;
+};
+
+static struct bvblendxlate blendxlate[64] = {
+	/**********************************************************************/
+	/* #0: color factor: 00 00 00 A:(1-C1,C1)=zero
+	       alpha factor: zero ==> 00 00 00 */
+	{
+		0x00,
+		0x00,
+
+		{
+			GCREG_BLENDING_MODE_ZERO,
+			GCREG_FACTOR_INVERSE_DISABLE,
+			BVSRC1USE(false), BVSRC2USE(false)
+		},
+
+		{
+			GCREG_BLENDING_MODE_ZERO,
+			GCREG_FACTOR_INVERSE_DISABLE,
+			BVSRC1USE(false), BVSRC2USE(false)
+		}
+	},
+
+	/* #1: color factor: 00 00 01 A:(1-C1,A1)=A1
+	       alpha factor: A1 ==> 00 00 01 or 00 10 01 */
+	{
+		BVBLENDMATCH(ONLY_A, INV_C1, NORM_A1),
+		BVBLENDMATCH(ONLY_A, INV_C2, NORM_A1),
+
+		{
+			GCREG_BLENDING_MODE_NORMAL,
+			GCREG_FACTOR_INVERSE_ENABLE,
+			BVSRC1USE(true), BVSRC2USE(false)
+		},
+
+		{
+			GCREG_BLENDING_MODE_NORMAL,
+			GCREG_FACTOR_INVERSE_DISABLE,
+			BVSRC1USE(true), BVSRC2USE(true)
+		}
+	},
+
+	/* #2: color factor: 00 00 10 A:(1-C1,C2)=undefined
+	       alpha factor: N/A */
+	BVBLENDUNDEFINED(),
+
+	/* #3: color factor: 00 00 11 A:(1-C1,A2)=A2
+	       alpha factor: A2 ==> 00 00 11 or 00 10 11 */
+	{
+		BVBLENDMATCH(ONLY_A, INV_C1, NORM_A2),
+		BVBLENDMATCH(ONLY_A, INV_C2, NORM_A2),
+
+		{
+			GCREG_BLENDING_MODE_NORMAL,
+			GCREG_FACTOR_INVERSE_DISABLE,
+			BVSRC1USE(true), BVSRC2USE(true)
+		},
+
+		{
+			GCREG_BLENDING_MODE_NORMAL,
+			GCREG_FACTOR_INVERSE_ENABLE,
+			BVSRC1USE(false), BVSRC2USE(true)
+		}
+	},
+
+	/* #4: color factor: 00 01 00 A:(1-A1,C1)=1-A1
+	       alpha factor: 1-A1 ==> 00 01 00 or 00 01 10 */
+	{
+		BVBLENDMATCH(ONLY_A, INV_A1, NORM_C1),
+		BVBLENDMATCH(ONLY_A, INV_A1, NORM_C2),
+
+		{
+			GCREG_BLENDING_MODE_INVERSED,
+			GCREG_FACTOR_INVERSE_ENABLE,
+			BVSRC1USE(true), BVSRC2USE(false)
+		},
+
+		{
+			GCREG_BLENDING_MODE_INVERSED,
+			GCREG_FACTOR_INVERSE_DISABLE,
+			BVSRC1USE(true), BVSRC2USE(true)
+		}
+	},
+
+	/* #5: color factor: 00 01 01 A:(1-A1,A1)=undefined
+	       alpha factor: N/A */
+	BVBLENDUNDEFINED(),
+
+	/* #6: color factor: 00 01 10 A:(1-A1,C2)=1-A1
+	       alpha factor: 1-A1 ==> 00 01 00 or 00 01 10 */
+	{
+		BVBLENDMATCH(ONLY_A, INV_A1, NORM_C1),
+		BVBLENDMATCH(ONLY_A, INV_A1, NORM_C2),
+
+		{
+			GCREG_BLENDING_MODE_INVERSED,
+			GCREG_FACTOR_INVERSE_ENABLE,
+			BVSRC1USE(true), BVSRC2USE(false)
+		},
+
+		{
+			GCREG_BLENDING_MODE_INVERSED,
+			GCREG_FACTOR_INVERSE_DISABLE,
+			BVSRC1USE(true), BVSRC2USE(true)
+		}
+	},
+
+	/* #7: color factor: 00 01 11 A:(1-A1,A2)=undefined
+	       alpha factor: N/A */
+	BVBLENDUNDEFINED(),
+
+	/* #8: color factor: 00 10 00 A:(1-C2,C1)=undefined
+	       alpha factor: N/A */
+	BVBLENDUNDEFINED(),
+
+	/* #9: color factor: 00 10 01 A:(1-C2,A1)=A1
+	       alpha factor: A1 ==> 00 00 01 or 00 10 01 */
+	{
+		BVBLENDMATCH(ONLY_A, INV_C1, NORM_A1),
+		BVBLENDMATCH(ONLY_A, INV_C2, NORM_A1),
+
+		{
+			GCREG_BLENDING_MODE_NORMAL,
+			GCREG_FACTOR_INVERSE_ENABLE,
+			BVSRC1USE(true), BVSRC2USE(false)
+		},
+
+		{
+			GCREG_BLENDING_MODE_NORMAL,
+			GCREG_FACTOR_INVERSE_DISABLE,
+			BVSRC1USE(true), BVSRC2USE(true)
+		}
+	},
+
+	/* #10: color factor: 00 10 10 A:(1-C2,C2)=undefined
+		alpha factor: N/A */
+	BVBLENDUNDEFINED(),
+
+	/* #11: color factor: 00 10 11 A:(1-C2,A2)=A2
+		alpha factor: A2 ==> 00 00 11 or 00 10 11 */
+	{
+		BVBLENDMATCH(ONLY_A, INV_C1, NORM_A2),
+		BVBLENDMATCH(ONLY_A, INV_C2, NORM_A2),
+
+		{
+			GCREG_BLENDING_MODE_NORMAL,
+			GCREG_FACTOR_INVERSE_DISABLE,
+			BVSRC1USE(true), BVSRC2USE(true)
+		},
+
+		{
+			GCREG_BLENDING_MODE_NORMAL,
+			GCREG_FACTOR_INVERSE_ENABLE,
+			BVSRC1USE(false), BVSRC2USE(true)
+		}
+	},
+
+	/* #12: color factor: 00 11 00 A:(1-A2,C1)=1-A2
+		alpha factor: 1-A2 ==> 00 11 00 or 00 11 10 */
+	{
+		BVBLENDMATCH(ONLY_A, INV_A2, NORM_C1),
+		BVBLENDMATCH(ONLY_A, INV_A2, NORM_C2),
+
+		{
+			GCREG_BLENDING_MODE_INVERSED,
+			GCREG_FACTOR_INVERSE_DISABLE,
+			BVSRC1USE(true), BVSRC2USE(true)
+		},
+
+		{
+			GCREG_BLENDING_MODE_INVERSED,
+			GCREG_FACTOR_INVERSE_ENABLE,
+			BVSRC1USE(false), BVSRC2USE(true)
+		}
+	},
+
+	/* #13: color factor: 00 11 01 A:(1-A2,A1)=undefined
+		alpha factor: N/A */
+	BVBLENDUNDEFINED(),
+
+	/* #14: color factor: 00 11 10 A:(1-A2,C2)=1-A2
+		alpha factor: 1-A2 ==> 00 11 00 or 00 11 10 */
+	{
+		BVBLENDMATCH(ONLY_A, INV_A2, NORM_C1),
+		BVBLENDMATCH(ONLY_A, INV_A2, NORM_C2),
+
+		{
+			GCREG_BLENDING_MODE_INVERSED,
+			GCREG_FACTOR_INVERSE_DISABLE,
+			BVSRC1USE(true), BVSRC2USE(true)
+		},
+
+		{
+			GCREG_BLENDING_MODE_INVERSED,
+			GCREG_FACTOR_INVERSE_ENABLE,
+			BVSRC1USE(false), BVSRC2USE(true)
+		}
+	},
+
+	/* #15: color factor: 00 11 11 A:(1-A2,A2)=undefined
+		alpha factor: N/A */
+	BVBLENDUNDEFINED(),
+
+	/**********************************************************************/
+	/* #16: color factor: 01 00 00 MIN:(1-C1,C1) ==> not supported
+		alpha factor: N/A */
+	BVBLENDUNDEFINED(),
+
+	/* #17: color factor: 01 00 01 MIN:(1-C1,A1) ==> not supported
+		alpha factor: N/A */
+	BVBLENDUNDEFINED(),
+
+	/* #18: color factor: 01 00 10 MIN:(1-C1,C2) ==> not supported
+		alpha factor: N/A */
+	BVBLENDUNDEFINED(),
+
+	/* #19: color factor: 01 00 11 MIN:(1-C1,A2) ==> not supported
+		alpha factor: N/A */
+	BVBLENDUNDEFINED(),
+
+	/* #20: color factor: 01 01 00 MIN:(1-A1,C1) ==> not supported
+		alpha factor: N/A */
+	BVBLENDUNDEFINED(),
+
+	/* #21: color factor: 01 01 01 MIN:(1-A1,A1) ==> not supported
+		alpha factor: N/A */
+	BVBLENDUNDEFINED(),
+
+	/* #22: color factor: 01 01 10 MIN:(1-A1,C2) ==> not supported
+		alpha factor: N/A */
+	BVBLENDUNDEFINED(),
+
+	/* #23: color factor: 01 01 11 MIN:(1-A1,A2)
+		alpha factor: one ==> 11 11 11 */
+	{
+		0x3F,
+		0x3F,
+
+		{
+			GCREG_BLENDING_MODE_SATURATED_DEST_ALPHA,
+			GCREG_FACTOR_INVERSE_DISABLE,
+			BVSRC1USE(true), BVSRC2USE(true)
+		},
+
+		{
+			GCREG_BLENDING_MODE_SATURATED_ALPHA,
+			GCREG_FACTOR_INVERSE_DISABLE,
+			BVSRC1USE(true), BVSRC2USE(true)
+		}
+	},
+
+	/* #24: color factor: 01 10 00 MIN:(1-C2,C1) ==> not supported
+		alpha factor: N/A */
+	BVBLENDUNDEFINED(),
+
+	/* #25: color factor: 01 10 01 MIN:(1-C2,A1) ==> not supported
+		alpha factor: N/A */
+	BVBLENDUNDEFINED(),
+
+	/* #26: color factor: 01 10 10 MIN:(1-C2,C2) ==> not supported
+		alpha factor: N/A */
+	BVBLENDUNDEFINED(),
+
+	/* #27: color factor: 01 10 11 MIN:(1-C2,A2) ==> not supported
+		alpha factor: N/A */
+	BVBLENDUNDEFINED(),
+
+	/* #28: color factor: 01 11 00 MIN:(1-A2,C1) ==> not supported
+		alpha factor: N/A */
+	BVBLENDUNDEFINED(),
+
+	/* #29: color factor: 01 11 01 MIN:(1-A2,A1)
+		alpha factor: one ==> 11 11 11 */
+	{
+		0x3F,
+		0x3F,
+
+		{
+			GCREG_BLENDING_MODE_SATURATED_ALPHA,
+			GCREG_FACTOR_INVERSE_DISABLE,
+			BVSRC1USE(true), BVSRC2USE(true)
+		},
+
+		{
+			GCREG_BLENDING_MODE_SATURATED_DEST_ALPHA,
+			GCREG_FACTOR_INVERSE_DISABLE,
+			BVSRC1USE(true), BVSRC2USE(true)
+		}
+	},
+
+	/* #30: color factor: 01 11 10 MIN:(1-A2,C2) ==> not supported
+		alpha factor: N/A */
+	BVBLENDUNDEFINED(),
+
+	/* #31: color factor: 01 11 11 MIN:(1-A2,A2) ==> not supported
+		alpha factor: N/A */
+	BVBLENDUNDEFINED(),
+
+	/**********************************************************************/
+	/* #32: color factor: 10 00 00 MAX:(1-C1,C1) ==> not supported
+		alpha factor: N/A */
+	BVBLENDUNDEFINED(),
+
+	/* #33: color factor: 10 00 01 MAX:(1-C1,A1) ==> not supported
+		alpha factor: N/A */
+	BVBLENDUNDEFINED(),
+
+	/* #34: color factor: 10 00 10 MAX:(1-C1,C2) ==> not supported
+		alpha factor: N/A */
+	BVBLENDUNDEFINED(),
+
+	/* #35: color factor: 10 00 11 MAX:(1-C1,A2) ==> not supported
+		alpha factor: N/A */
+	BVBLENDUNDEFINED(),
+
+	/* #36: color factor: 10 01 00 MAX:(1-A1,C1) ==> not supported
+		alpha factor: N/A */
+	BVBLENDUNDEFINED(),
+
+	/* #37: color factor: 10 01 01 MAX:(1-A1,A1) ==> not supported
+		alpha factor: N/A */
+	BVBLENDUNDEFINED(),
+
+	/* #38: color factor: 10 01 10 MAX:(1-A1,C2) ==> not supported
+		alpha factor: N/A */
+	BVBLENDUNDEFINED(),
+
+	/* #39: color factor: 10 01 11 MAX:(1-A1,A2) ==> not supported
+		alpha factor: N/A */
+	BVBLENDUNDEFINED(),
+
+	/* #40: color factor: 10 10 00 MAX:(1-C2,C1) ==> not supported
+		alpha factor: N/A */
+	BVBLENDUNDEFINED(),
+
+	/* #41: color factor: 10 10 01 MAX:(1-C2,A1) ==> not supported
+		alpha factor: N/A */
+	BVBLENDUNDEFINED(),
+
+	/* #42: color factor: 10 10 10 MAX:(1-C2,C2) ==> not supported
+		alpha factor: N/A */
+	BVBLENDUNDEFINED(),
+
+	/* #43: color factor: 10 10 11 MAX:(1-C2,A2) ==> not supported
+		alpha factor: N/A */
+	BVBLENDUNDEFINED(),
+
+	/* #44: color factor: 10 11 00 MAX:(1-A2,C1) ==> not supported
+		alpha factor: N/A */
+	BVBLENDUNDEFINED(),
+
+	/* #45: color factor: 10 11 01 MAX:(1-A2,A1) ==> not supported
+		alpha factor: N/A */
+	BVBLENDUNDEFINED(),
+
+	/* #46: color factor: 10 11 10 MAX:(1-A2,C2) ==> not supported
+		alpha factor: N/A */
+	BVBLENDUNDEFINED(),
+
+	/* #47: color factor: 10 11 11 MAX:(1-A2,A2) ==> not supported
+		alpha factor: N/A */
+	BVBLENDUNDEFINED(),
+
+	/**********************************************************************/
+	/* #48: color factor: 11 00 00 C:(1-C1,C1)=undefined
+		alpha factor: N/A */
+	BVBLENDUNDEFINED(),
+
+	/* #49: color factor: 11 00 01 C:(1-C1,A1)=1-C1
+		alpha factor: 1-A1 ==> 00 01 00 or 00 01 10 */
+	{
+		BVBLENDMATCH(ONLY_A, INV_A1, NORM_C1),
+		BVBLENDMATCH(ONLY_A, INV_A1, NORM_C2),
+
+		{
+			GCREG_BLENDING_MODE_COLOR_INVERSED,
+			GCREG_FACTOR_INVERSE_ENABLE,
+			BVSRC1USE(true), BVSRC2USE(false)
+		},
+
+		{
+			GCREG_BLENDING_MODE_COLOR_INVERSED,
+			GCREG_FACTOR_INVERSE_DISABLE,
+			BVSRC1USE(true), BVSRC2USE(true)
+		}
+	},
+
+	/* #50: color factor: 11 00 10 C:(1-C1,C2)=undefined
+		alpha factor: N/A */
+	BVBLENDUNDEFINED(),
+
+	/* #51: color factor: 11 00 11 C:(1-C1,A2)=1-C1
+		alpha factor: 1-A1 ==> 00 01 00 or 00 01 10 */
+	{
+		BVBLENDMATCH(ONLY_A, INV_A1, NORM_C1),
+		BVBLENDMATCH(ONLY_A, INV_A1, NORM_C2),
+
+		{
+			GCREG_BLENDING_MODE_COLOR_INVERSED,
+			GCREG_FACTOR_INVERSE_ENABLE,
+			BVSRC1USE(true), BVSRC2USE(false)
+		},
+
+		{
+			GCREG_BLENDING_MODE_COLOR_INVERSED,
+			GCREG_FACTOR_INVERSE_DISABLE,
+			BVSRC1USE(true), BVSRC2USE(true)
+		}
+	},
+
+	/* #52: color factor: 11 01 00 C:(1-A1,C1)=C1
+		alpha factor: A1 ==> 00 00 01 or 00 10 01 */
+	{
+		BVBLENDMATCH(ONLY_A, INV_C1, NORM_A1),
+		BVBLENDMATCH(ONLY_A, INV_C2, NORM_A1),
+
+		{
+			GCREG_BLENDING_MODE_COLOR,
+			GCREG_FACTOR_INVERSE_ENABLE,
+			BVSRC1USE(true), BVSRC2USE(false)
+		},
+
+		{
+			GCREG_BLENDING_MODE_COLOR,
+			GCREG_FACTOR_INVERSE_DISABLE,
+			BVSRC1USE(true), BVSRC2USE(true)
+		}
+	},
+
+	/* #53: color factor: 11 01 01 C:(1-A1,A1)=undefined
+		alpha factor: N/A */
+	BVBLENDUNDEFINED(),
+
+	/* #54: color factor: 11 01 10 C:(1-A1,C2)=C2
+		alpha factor: A2 ==> 00 00 11 or 00 10 11 */
+	{
+		BVBLENDMATCH(ONLY_A, INV_C1, NORM_A2),
+		BVBLENDMATCH(ONLY_A, INV_C2, NORM_A2),
+
+		{
+			GCREG_BLENDING_MODE_COLOR,
+			GCREG_FACTOR_INVERSE_DISABLE,
+			BVSRC1USE(true), BVSRC2USE(true)
+		},
+
+		{
+			GCREG_BLENDING_MODE_COLOR,
+			GCREG_FACTOR_INVERSE_ENABLE,
+			BVSRC1USE(false), BVSRC2USE(true)
+		}
+	},
+
+	/* #55: color factor: 11 01 11 C:(1-A1,A2)=undefined
+		alpha factor: N/A */
+	BVBLENDUNDEFINED(),
+
+	/* #56: color factor: 11 10 00 C:(1-C2,C1)=undefined
+		alpha factor: N/A */
+	BVBLENDUNDEFINED(),
+
+	/* #57: color factor: 11 10 01 C:(1-C2,A1)=1-C2
+		alpha factor: 1-A2 ==> 00 11 00 or 00 11 10 */
+	{
+		BVBLENDMATCH(ONLY_A, INV_A2, NORM_C1),
+		BVBLENDMATCH(ONLY_A, INV_A2, NORM_C2),
+
+		{
+			GCREG_BLENDING_MODE_COLOR_INVERSED,
+			GCREG_FACTOR_INVERSE_DISABLE,
+			BVSRC1USE(true), BVSRC2USE(true)
+		},
+
+		{
+			GCREG_BLENDING_MODE_COLOR_INVERSED,
+			GCREG_FACTOR_INVERSE_ENABLE,
+			BVSRC1USE(false), BVSRC2USE(true)
+		}
+	},
+
+	/* #58: color factor: 11 10 10 C:(1-C2,C2)=undefined
+		alpha factor: N/A */
+	BVBLENDUNDEFINED(),
+
+	/* #59: color factor: 11 10 11 C:(1-C2,A2)=1-C2
+		alpha factor: 1-A2 ==> 00 11 00 or 00 11 10 */
+	{
+		BVBLENDMATCH(ONLY_A, INV_A2, NORM_C1),
+		BVBLENDMATCH(ONLY_A, INV_A2, NORM_C2),
+
+		{
+			GCREG_BLENDING_MODE_COLOR_INVERSED,
+			GCREG_FACTOR_INVERSE_DISABLE,
+			BVSRC1USE(true), BVSRC2USE(true)
+		},
+
+		{
+			GCREG_BLENDING_MODE_COLOR_INVERSED,
+			GCREG_FACTOR_INVERSE_ENABLE,
+			BVSRC1USE(false), BVSRC2USE(false)
+		}
+	},
+
+	/* #60: color factor: 11 11 00 C:(1-A2,C1)=C1
+		alpha factor: A1 ==> 00 00 01 or 00 10 01 */
+	{
+		BVBLENDMATCH(ONLY_A, INV_C1, NORM_A1),
+		BVBLENDMATCH(ONLY_A, INV_C2, NORM_A1),
+
+		{
+			GCREG_BLENDING_MODE_COLOR,
+			GCREG_FACTOR_INVERSE_ENABLE,
+			BVSRC1USE(true), BVSRC2USE(false)
+		},
+
+		{
+			GCREG_BLENDING_MODE_COLOR,
+			GCREG_FACTOR_INVERSE_DISABLE,
+			BVSRC1USE(true), BVSRC2USE(true)
+		}
+	},
+
+	/* #61: color factor: 11 11 01 C:(1-A2,A1)=undefined
+		alpha factor: N/A */
+	BVBLENDUNDEFINED(),
+
+	/* #62: color factor: 11 11 10 C:(1-A2,C2)=C2
+		alpha factor: A2 ==> 00 00 11 or 00 10 11 */
+	{
+		BVBLENDMATCH(ONLY_A, INV_C1, NORM_A2),
+		BVBLENDMATCH(ONLY_A, INV_C2, NORM_A2),
+
+		{
+			GCREG_BLENDING_MODE_COLOR,
+			GCREG_FACTOR_INVERSE_DISABLE,
+			BVSRC1USE(true), BVSRC2USE(true)
+		},
+
+		{
+			GCREG_BLENDING_MODE_COLOR,
+			GCREG_FACTOR_INVERSE_ENABLE,
+			BVSRC1USE(false), BVSRC2USE(true)
+		}
+	},
+
+	/* #63: color factor: 11 11 11 C:(1-A2,A2)=one
+		alpha factor: one ==> 11 11 11 */
+	{
+		0x3F,
+		0x3F,
+
+		{
+			GCREG_BLENDING_MODE_ONE,
+			GCREG_FACTOR_INVERSE_DISABLE,
+			BVSRC1USE(true), BVSRC2USE(false)
+		},
+
+		{
+			GCREG_BLENDING_MODE_ONE,
+			GCREG_FACTOR_INVERSE_DISABLE,
+			BVSRC1USE(false), BVSRC2USE(true)
+		}
+	}
+};
+
+enum bverror parse_blend(struct bvbltparams *bvbltparams,
+			 enum bvblend blend,
+			 struct gcalpha *gca)
+{
+	enum bverror bverror;
+	unsigned int global;
+	unsigned int k1, k2, k3, k4;
+	struct bvblendxlate *k1_xlate;
+	struct bvblendxlate *k2_xlate;
+	unsigned int alpha;
+
+	GCENTER(GCZONE_BLEND);
+
+	if ((blend & BVBLENDDEF_REMOTE) != 0) {
+		BVSETBLTERROR(BVERR_BLEND, "remote alpha not supported");
+		goto exit;
+	}
+
+	global = (blend & BVBLENDDEF_GLOBAL_MASK) >> BVBLENDDEF_GLOBAL_SHIFT;
+
+	switch (global) {
+	case (BVBLENDDEF_GLOBAL_NONE >> BVBLENDDEF_GLOBAL_SHIFT):
+		GCDBG(GCZONE_BLEND, "BVBLENDDEF_GLOBAL_NONE\n");
+
+		gca->globalcolor = 0;
+		gca->globalcolorenable = false;
+		break;
+
+	case (BVBLENDDEF_GLOBAL_UCHAR >> BVBLENDDEF_GLOBAL_SHIFT):
+		GCDBG(GCZONE_BLEND, "BVBLENDDEF_GLOBAL_UCHAR (0x%02X)\n",
+		      bvbltparams->globalalpha.size8);
+
+		gca->globalcolor
+			= ((unsigned int) bvbltparams->globalalpha.size8) << 24;
+		gca->globalcolorenable = true;
+		break;
+
+	case (BVBLENDDEF_GLOBAL_FLOAT >> BVBLENDDEF_GLOBAL_SHIFT):
+		GCDBG(GCZONE_BLEND, "BVBLENDDEF_GLOBAL_FLOAT (0x%08X)\n",
+		      *(unsigned int *) &bvbltparams->globalalpha.fp);
+
+		alpha = gcfp2norm8(bvbltparams->globalalpha.fp);
+		GCDBG(GCZONE_BLEND, "converted alpha = 0x%02X\n", alpha);
+
+		gca->globalcolor = alpha << 24;
+		gca->globalcolorenable = true;
+		break;
+
+	default:
+		BVSETBLTERROR(BVERR_BLEND, "invalid global alpha mode");
+		goto exit;
+	}
+
+	/*
+		Co = k1 x C1 + k2 x C2
+		Ao = k3 x A1 + k4 x A2
+	*/
+
+	k1 = (blend >> 18) & 0x3F;
+	k2 = (blend >> 12) & 0x3F;
+	k3 = (blend >>  6) & 0x3F;
+	k4 =  blend        & 0x3F;
+
+	GCDBG(GCZONE_BLEND, "k1 = %d\n", k1);
+	GCDBG(GCZONE_BLEND, "k2 = %d\n", k2);
+	GCDBG(GCZONE_BLEND, "k3 = %d\n", k3);
+	GCDBG(GCZONE_BLEND, "k4 = %d\n", k4);
+
+	k1_xlate = &blendxlate[k1];
+	k2_xlate = &blendxlate[k2];
+
+	if (((k3 != k1_xlate->match1) && (k3 != k1_xlate->match2)) ||
+		((k4 != k2_xlate->match1) && (k4 != k2_xlate->match2))) {
+		BVSETBLTERROR(BVERR_BLEND,
+			      "not supported coefficient combination");
+		goto exit;
+	}
+
+	gca->k1 = &k1_xlate->k1;
+	gca->k2 = &k2_xlate->k2;
+
+	gca->src1used = gca->k1->src1used | gca->k2->src1used;
+	gca->src2used = gca->k1->src2used | gca->k2->src2used;
+
+	bverror = BVERR_NONE;
+
+exit:
+	GCEXITARG(BVERR_BLEND, "bv%s = %d\n",
+		  (bverror == BVERR_NONE) ? "result" : "error", bverror);
+	return bverror;
+}
+
+
+/*******************************************************************************
+ * Rotation and mirror.
+ */
+
+#define BVFLAG_FLIP_MASK	0x00000003
+
+#define BVFLAG_FLIP_SRC1_SHIFT	14
+#define BVFLAG_FLIP_SRC2_SHIFT	16
+#define BVFLAG_FLIP_MASK_SHIFT	18
+
+#define GCREG_MIRROR_NONE	0x0
+#define GCREG_MIRROR_X		0x1
+#define GCREG_MIRROR_Y		0x2
+#define GCREG_MIRROR_XY		0x3
+
+#define GCREG_ROT_ANGLE_ROT0	0x0
+#define GCREG_ROT_ANGLE_ROT90	0x4
+#define GCREG_ROT_ANGLE_ROT180	0x5
+#define GCREG_ROT_ANGLE_ROT270	0x6
+
+#define ROT_ANGLE_INVALID	-1
+#define ROT_ANGLE_0		0
+#define ROT_ANGLE_90		1
+#define ROT_ANGLE_180		2
+#define ROT_ANGLE_270		3
+
+/* NOTE: BLTsville rotation is defined conunter clock wise. */
+const unsigned int rotencoding[] = {
+	GCREG_ROT_ANGLE_ROT0,		/* ROT_ANGLE_0 */
+	GCREG_ROT_ANGLE_ROT270,		/* ROT_ANGLE_90 */
+	GCREG_ROT_ANGLE_ROT180,		/* ROT_ANGLE_180 */
+	GCREG_ROT_ANGLE_ROT90		/* ROT_ANGLE_270 */
+};
+
+static inline int get_angle(int orientation)
+{
+	int angle;
+
+	/* Normalize the angle. */
+	angle = orientation % 360;
+
+	/* Flip to positive. */
+	if (angle < 0)
+		angle = 360 + angle;
+
+	/* Translate the angle. */
+	switch (angle) {
+	case 0:   return ROT_ANGLE_0;
+	case 90:  return ROT_ANGLE_90;
+	case 180: return ROT_ANGLE_180;
+	case 270: return ROT_ANGLE_270;
+	}
+
+	/* Not supported angle. */
+	return ROT_ANGLE_INVALID;
+}
+
+
+/*******************************************************************************
+ * Surface compare and validation.
+ */
+
+bool null_rect(struct gcrect *gcrect)
+{
+	return (gcrect->left == gcrect->right) &&
+	       (gcrect->top  == gcrect->bottom);
+}
+
+bool valid_rect(struct gcsurface *gcsurface, struct gcrect *gcrect)
+{
+	int width, height;
+
+	if ((gcrect->left < 0) || (gcrect->top < 0)) {
+		GCERR("invalid rectangle origin: %d,%d.\n",
+		      gcrect->left, gcrect->top);
+		return false;
+	}
+
+	width  = gcrect->right  - gcrect->left;
+	height = gcrect->bottom - gcrect->top;
+	if ((width < 0) || (height < 0)) {
+		GCERR("invalid rectangle size: %d,%d.\n",
+		      width, height);
+		return false;
+	}
+
+	if (gcrect->right > (int) gcsurface->width) {
+		GCERR("right coordinate (%d) exceeds surface width (%d).\n",
+		      gcrect->right, gcsurface->width);
+		return false;
+	}
+
+	if (gcrect->bottom > (int) gcsurface->height) {
+		GCERR("bottom coordinate (%d) exceeds surface height (%d).\n",
+		      gcrect->bottom, gcsurface->height);
+		return false;
+	}
+
+	return true;
+}
+
+static bool valid_geom(struct gcsurface *gcsurface)
+{
+	unsigned int size;
+	unsigned int height;
+
+	/* Compute the size of the surface. */
+	size = (gcsurface->width * gcsurface->height *
+		gcsurface->format.allocbitspp) / 8;
+
+	/* Make sure the size is not greater then the surface. */
+	if (size > gcsurface->buf.desc->length) {
+		GCERR("invalid geometry detected:\n");
+		GCERR("  specified dimensions: %dx%d, %d bitspp\n",
+		      gcsurface->width,
+		      gcsurface->height,
+		      gcsurface->format.bitspp);
+		GCERR("  surface size based on the dimensions: %d\n",
+		      size);
+		GCERR("  specified surface size: %lu\n",
+		      gcsurface->buf.desc->length);
+		return false;
+	}
+
+	/* Determine the height of the image. */
+	height = ((gcsurface->angle % 2) == 0)
+	       ? gcsurface->height
+	       : gcsurface->width;
+
+	/* Compute the size using the stide. */
+	size = gcsurface->stride1 * height;
+
+	/* Make sure the size is not greater then the surface. */
+	if (size > gcsurface->buf.desc->length) {
+		GCERR("invalid geometry detected:\n");
+		GCERR("  specified dimensions: %dx%d, %d bitspp\n",
+		      gcsurface->width,
+		      gcsurface->height,
+		      gcsurface->format.bitspp);
+		GCERR("  physical image height = %d\n", height);
+		GCERR("  image stride = %d\n", gcsurface->stride1);
+		GCERR("  computed surface size = %d\n", size);
+		GCERR("  specified surface size: %lu\n",
+		      gcsurface->buf.desc->length);
+		return false;
+	}
+
+	return true;
+}
+
+enum bverror valid_stride(struct bvbltparams *bvbltparams,
+			  struct gcsurface *gcsurface)
+{
+	enum bverror bverror;
+	struct gccontext *gccontext = get_context();
+	struct bvformatxlate *format = &gcsurface->format;
+	bool srcsurface;
+	unsigned int alignment;
+
+	/* Is this the source? */
+	srcsurface = (gcsurface->index >= 0);
+
+	if (gccontext->gccaps.strictalign) {
+		if (format->type == BVFMT_YUV) {
+			if (srcsurface) {
+				alignment = (format->cs.yuv.planecount == 1)
+					  ? 16 - 1
+					  : 8 - 1;
+			} else {
+				alignment = ~0U;
+			}
+		} else {
+			alignment = 16 - 1;
+		}
+	} else {
+		if (format->type == BVFMT_YUV) {
+			if (format->cs.yuv.planecount == 1) {
+				alignment = 4 - 1;
+			} else {
+				alignment = (srcsurface)
+					  ? 8 - 1
+					  : ~0U;
+			}
+		} else {
+			alignment = (format->bitspp / 8) - 1;
+		}
+	}
+
+	if (alignment == ~0U) {
+		if (srcsurface) {
+			BVSETBLTERROR((gcsurface->index == 0)
+						? BVERR_SRC1GEOM_FORMAT
+						: BVERR_SRC2GEOM_FORMAT,
+				      "source %d format unsupported",
+				      gcsurface->index);
+		} else {
+			BVSETBLTERROR(BVERR_DSTGEOM_FORMAT,
+				      "destination format unsupported");
+		}
+
+		return bverror;
+	}
+
+	if ((gcsurface->stride1 & alignment) != 0) {
+		if (srcsurface) {
+			BVSETBLTERROR((gcsurface->index == 0)
+						? BVERR_SRC1GEOM_STRIDE
+						: BVERR_SRC2GEOM_STRIDE,
+				      "source %d stride must be "
+				      "%d pixel aligned.",
+				      gcsurface->index,
+				      alignment + 1);
+		} else {
+			BVSETBLTERROR(BVERR_DSTGEOM_FORMAT,
+				      "destination format unsupported");
+		}
+
+		return bverror;
+	}
+
+	return BVERR_NONE;
+}
+
+int get_pixel_offset(struct gcsurface *gcsurface, int offset)
+{
+	struct gccontext *gccontext = get_context();
+	unsigned int alignment;
+	int byteoffset;
+	unsigned int alignedoffset;
+	int pixeloffset;
+
+	GCENTERARG(GCZONE_OFFSET, "gcsurface=0x%08X, offset=%d\n",
+		   gcsurface, offset);
+
+	if (gccontext->gccaps.strictalign) {
+		if ((gcsurface->format.type == BVFMT_YUV) &&
+		    (gcsurface->format.cs.yuv.planecount > 1))
+			alignment = 64 - 1;
+		else
+			alignment = 16 - 1;
+	} else {
+		if (gcsurface->format.type == BVFMT_YUV) {
+			if (gcsurface->format.cs.yuv.planecount == 1)
+				alignment = 4 - 1;
+			else
+				alignment = 64 - 1;
+		} else {
+			alignment = (gcsurface->format.bitspp / 8) - 1;
+		}
+	}
+
+	GCDBG(GCZONE_OFFSET, "bpp = %d\n", gcsurface->format.bitspp);
+	GCDBG(GCZONE_OFFSET, "alignment = %d\n", alignment);
+
+	/* Determine offset in bytes from the base modified by the
+	 * given offset. */
+	if (gcsurface->buf.desc->auxtype == BVAT_PHYSDESC) {
+		struct bvphysdesc *bvphysdesc;
+		bvphysdesc = (struct bvphysdesc *)
+			     gcsurface->buf.desc->auxptr;
+		GCDBG(GCZONE_OFFSET, "physical descriptor = 0x%08X\n",
+		      bvphysdesc);
+		GCDBG(GCZONE_OFFSET, "first page = 0x%08X\n",
+			bvphysdesc->pagearray[0]);
+		GCDBG(GCZONE_OFFSET, "page offset = 0x%08X\n",
+			bvphysdesc->pageoffset);
+
+		byteoffset = bvphysdesc->pageoffset + offset;
+	} else {
+		GCDBG(GCZONE_OFFSET, "no physical descriptor.\n");
+		byteoffset = (unsigned int)
+			     gcsurface->buf.desc->virtaddr + offset;
+	}
+
+	GCDBG(GCZONE_OFFSET, "byteoffset = %d\n", byteoffset);
+
+	/* Compute the aligned offset. */
+	alignedoffset = byteoffset & alignment;
+
+	/* Convert to pixels. */
+	pixeloffset = alignedoffset * 8 / gcsurface->format.bitspp;
+
+	GCDBG(GCZONE_OFFSET, "alignedoffset = %d\n", alignedoffset);
+	GCDBG(GCZONE_OFFSET, "pixeloffset = %d\n", -pixeloffset);
+
+	GCEXIT(GCZONE_OFFSET);
+	return -pixeloffset;
+}
+
+void rotate_rect(int angle,
+		 struct gcsurface *gcsurface, struct gcrect *rect)
+{
+	unsigned int width, height;
+	struct gcrect temprect;
+
+	GCENTER(GCZONE_SURF);
+
+	GCDBG(GCZONE_SURF, "adjustment angle = %d\n",
+	      angle);
+	GCDBG(GCZONE_SURF, "geom size = %dx%d\n",
+	      gcsurface->width, gcsurface->height);
+
+	switch (angle) {
+	case ROT_ANGLE_0:
+		break;
+
+	case ROT_ANGLE_90:
+		width  = gcsurface->width;
+		height = gcsurface->height;
+
+		temprect.left   = height - rect->bottom;
+		temprect.top    = rect->left;
+		temprect.right  = height - rect->top;
+		temprect.bottom = rect->right;
+
+		*rect = temprect;
+		break;
+
+	case ROT_ANGLE_180:
+		width  = gcsurface->width;
+		height = gcsurface->height;
+
+		temprect.left   = width  - rect->right;
+		temprect.top    = height - rect->bottom;
+		temprect.right  = width  - rect->left;
+		temprect.bottom = height - rect->top;
+
+		*rect = temprect;
+		break;
+
+	case ROT_ANGLE_270:
+		width  = gcsurface->width;
+		height = gcsurface->height;
+
+		temprect.left   = rect->top;
+		temprect.top    = width - rect->right;
+		temprect.right  = rect->bottom;
+		temprect.bottom = width - rect->left;
+
+		*rect = temprect;
+		break;
+	}
+
+	GCEXIT(GCZONE_SURF);
+}
+
+void rotate_geom(int angle, struct gcsurface *gcsurface)
+{
+	GCENTER(GCZONE_SURF);
+
+	GCDBG(GCZONE_SURF, "adjustment angle = %d\n",
+	      angle);
+	GCDBG(GCZONE_SURF, "geom angle = %d\n",
+	      gcsurface->angle);
+	GCDBG(GCZONE_SURF, "geom size = %dx%d\n",
+	      gcsurface->width, gcsurface->height);
+
+	if ((angle % 2) != 0) {
+		unsigned int width, height;
+
+		width  = gcsurface->width;
+		height = gcsurface->height;
+
+		gcsurface->width  = height;
+		gcsurface->height = width;
+	}
+
+	gcsurface->angle = (gcsurface->angle + angle) % 4;
+	GCDBG(GCZONE_SURF, "new geom angle = %d\n",
+	      gcsurface->angle);
+	GCDBG(GCZONE_SURF, "new geom size = %dx%d\n",
+	      gcsurface->width, gcsurface->height);
+
+	GCEXIT(GCZONE_SURF);
+}
+
+void adjust_angle(struct gcsurface *srcinfo, struct gcsurface *dstinfo)
+{
+	int srcangle, dstangle;
+	struct gcrect *srcorig;
+	struct gcrect *dstorig, *dstclip, *dstadj;
+	struct gcrect *dstorigaux, *dstclipaux, *dstadjaux;
+
+	GCENTER(GCZONE_SURF);
+
+	/* Determine adjustment angles. */
+	srcangle = srcinfo->adjangle;
+	dstangle = (4 - (dstinfo->adjangle - srcangle)) % 4;
+
+	GCDBG(GCZONE_SURF, "source adjustment = %d deg.\n", srcangle * 90);
+	GCDBG(GCZONE_SURF, "destination adjusment = %d deg.\n", dstangle * 90);
+
+	/* Adjust the source. */
+	if (srcangle != 0) {
+		srcorig = &srcinfo->rect.orig;
+
+		rotate_rect(srcangle, srcinfo, srcorig);
+		rotate_geom(srcangle, srcinfo);
+
+		GCPRINT_RECT(GCZONE_SURF, "original src (rot)", srcorig);
+	}
+
+	/* Adjust the destination. */
+	if (dstangle != 0) {
+		dstorig = &dstinfo->rect.orig;
+		dstclip = &dstinfo->rect.clip;
+		dstadj = &dstinfo->rect.adj;
+
+		rotate_rect(dstangle, dstinfo, dstorig);
+		rotate_rect(dstangle, dstinfo, dstclip);
+		rotate_rect(dstangle, dstinfo, dstadj);
+
+		GCPRINT_RECT(GCZONE_SURF, "original dst (rot)", dstorig);
+		GCPRINT_RECT(GCZONE_SURF, "clipped dst (rot)", dstclip);
+		GCPRINT_RECT(GCZONE_SURF, "adjusted dst (rot)", dstadj);
+
+		if (dstinfo->haveaux) {
+			dstorigaux = &dstinfo->auxrect.orig;
+			dstclipaux = &dstinfo->auxrect.clip;
+			dstadjaux = &dstinfo->auxrect.adj;
+
+			rotate_rect(dstangle, dstinfo, dstorigaux);
+			rotate_rect(dstangle, dstinfo, dstclipaux);
+			rotate_rect(dstangle, dstinfo, dstadjaux);
+
+			GCPRINT_RECT(GCZONE_SURF, "original aux dst (rot)",
+				     dstorigaux);
+			GCPRINT_RECT(GCZONE_SURF, "clipped aux dst (rot)",
+				     dstclipaux);
+			GCPRINT_RECT(GCZONE_SURF, "adjusted aux dst (rot)",
+				     dstadjaux);
+		}
+
+		rotate_geom(dstangle, dstinfo);
+
+		/* Make sure the new destination is programmed. */
+		dstinfo->surfdirty = true;
+	}
+
+	GCEXIT(GCZONE_SURF);
+}
+
+void process_rotation(struct gcsurface *gcsurface)
+{
+	int offsetX, offsetY;
+	struct gcrect *clip;
+	struct gcrect *adj;
+	struct gcrect *clipaux;
+	struct gcrect *adjaux;
+
+	GCENTER(GCZONE_SURF);
+
+	switch (gcsurface->angle) {
+	case ROT_ANGLE_0:
+		/* Determine the origin offset. */
+		offsetX = gcsurface->xpixalign;
+		offsetY = gcsurface->ypixalign;
+
+		/* Determine geometry size. */
+		gcsurface->adjwidth  = gcsurface->width
+				     - gcsurface->xpixalign;
+		gcsurface->adjheight = gcsurface->height
+				     - gcsurface->ypixalign;
+
+		/* Determine the physical size. */
+		gcsurface->physwidth  = gcsurface->adjwidth;
+		gcsurface->physheight = gcsurface->adjheight;
+		break;
+
+	case ROT_ANGLE_90:
+		/* Determine the origin offset. */
+		offsetX = gcsurface->ypixalign;
+		offsetY = gcsurface->xpixalign;
+
+		/* Determine geometry size. */
+		gcsurface->adjwidth  = gcsurface->width
+				     - gcsurface->ypixalign;
+		gcsurface->adjheight = gcsurface->height
+				     - gcsurface->xpixalign;
+
+		/* Determine the physical size. */
+		gcsurface->physwidth  = gcsurface->adjheight;
+		gcsurface->physheight = gcsurface->adjwidth;
+		break;
+
+	case ROT_ANGLE_180:
+		/* Determine the origin offset. */
+		offsetX = 0;
+		offsetY = 0;
+
+		/* Determine geometry size. */
+		gcsurface->adjwidth  = gcsurface->width
+				     - gcsurface->xpixalign;
+		gcsurface->adjheight = gcsurface->height
+				     - gcsurface->ypixalign;
+
+		/* Determine the physical size. */
+		gcsurface->physwidth  = gcsurface->adjwidth;
+		gcsurface->physheight = gcsurface->adjheight;
+		break;
+
+	case ROT_ANGLE_270:
+		/* Determine the origin offset. */
+		offsetX = 0;
+		offsetY = 0;
+
+		/* Determine geometry size. */
+		gcsurface->adjwidth  = gcsurface->width
+				     - gcsurface->ypixalign;
+		gcsurface->adjheight = gcsurface->height
+				     - gcsurface->xpixalign;
+
+		/* Determine the physical size. */
+		gcsurface->physwidth  = gcsurface->adjheight;
+		gcsurface->physheight = gcsurface->adjwidth;
+		break;
+
+	default:
+		offsetX = 0;
+		offsetY = 0;
+	}
+
+	/* Get shortcuts to the destination rectangles. */
+	clip = &gcsurface->rect.clip;
+	adj = &gcsurface->rect.adj;
+
+	/* Compute adjusted destination rectangle. */
+	adj->left   = clip->left   - offsetX;
+	adj->top    = clip->top    - offsetY;
+	adj->right  = clip->right  - offsetX;
+	adj->bottom = clip->bottom - offsetY;
+
+	GCPRINT_RECT(GCZONE_SURF, "adjusted", adj);
+
+	if (gcsurface->haveaux) {
+		/* Get shortcuts to the destination aux rectangles. */
+		clipaux = &gcsurface->auxrect.clip;
+		adjaux = &gcsurface->auxrect.adj;
+
+		/* Compute adjusted destination rectangle. */
+		adjaux->left   = clipaux->left   - offsetX;
+		adjaux->top    = clipaux->top    - offsetY;
+		adjaux->right  = clipaux->right  - offsetX;
+		adjaux->bottom = clipaux->bottom - offsetY;
+
+		GCPRINT_RECT(GCZONE_SURF, "adjusted aux", adjaux);
+	}
+
+	GCDBG(GCZONE_SURF, "aligned geometry size = %dx%d\n",
+		gcsurface->adjwidth, gcsurface->adjheight);
+	GCDBG(GCZONE_SURF, "aligned physical size = %dx%d\n",
+		gcsurface->physwidth, gcsurface->physheight);
+	GCDBG(GCZONE_SURF, "origin offset (pixels) = %d,%d\n",
+		offsetX, offsetY);
+
+	GCEXIT(GCZONE_SURF);
+}
+
+enum bverror parse_destination(struct bvbltparams *bvbltparams,
+			       struct gcbatch *batch)
+{
+	enum bverror bverror = BVERR_NONE;
+	struct gcsurface *dstinfo;
+	struct gcrect *dstorig;
+	struct gcrect *dstclip;
+	struct gcrect *dstorigaux = NULL;
+	struct gcrect *dstclipaux = NULL;
+
+	GCENTER(GCZONE_DEST);
+
+	GCDBG(GCZONE_DEST, "parsing destination\n");
+
+	/* Get a shortcut to the destination surface descriptor. */
+	dstinfo = &batch->dstinfo;
+
+	/* Did the destination surface change? */
+	if (dstinfo->surfdirty) {
+		struct bvsurfgeom *dstgeom;
+
+		/* Shortcut to the geometry. */
+		dstgeom = bvbltparams->dstgeom;
+
+		/* Initialize the destination descriptor. */
+		dstinfo->index = -1;
+		dstinfo->buf.desc = bvbltparams->dstdesc;
+		dstinfo->width = dstgeom->width;
+		dstinfo->height = dstgeom->height;
+		dstinfo->stride1 = dstgeom->virtstride;
+
+		/* Parse the destination format. */
+		if (parse_format(bvbltparams, dstgeom->format,
+				 &dstinfo->format) != BVERR_NONE) {
+			bverror = BVERR_DSTGEOM_FORMAT;
+			goto exit;
+		}
+
+		/* Parse orientation. */
+		dstinfo->angle = get_angle(dstgeom->orientation);
+		if (dstinfo->angle == ROT_ANGLE_INVALID) {
+			BVSETBLTERROR(BVERR_DSTGEOM,
+				      "unsupported destination orientation %d.",
+				      dstgeom->orientation);
+			goto exit;
+		}
+
+		/* If angle has been modified previosuly, it means that
+		 * the rectangles have been rotated, make sure they are
+		 * reset back to the original ones. */
+		if (dstinfo->adjangle != 0) {
+			dstinfo->rectdirty = true;
+
+			/* Reset destination adjust angle. */
+			dstinfo->adjangle = 0;
+		}
+
+		/* Compute the destination alignments needed to compensate
+		 * for the surface base address misalignment if any. */
+		dstinfo->xpixalign = get_pixel_offset(dstinfo, 0);
+		dstinfo->ypixalign = 0;
+		dstinfo->bytealign1 = (dstinfo->xpixalign
+				    * (int) dstinfo->format.bitspp) / 8;
+
+		GCDBG(GCZONE_DEST, "  buffer length = %d\n",
+		      dstinfo->buf.desc->length);
+		GCDBG(GCZONE_DEST, "  rotation %d degrees.\n",
+		      dstinfo->angle * 90);
+
+		if (dstinfo->buf.desc->auxtype == BVAT_PHYSDESC) {
+			struct bvphysdesc *bvphysdesc;
+			bvphysdesc = (struct bvphysdesc *)
+				     dstinfo->buf.desc->auxptr;
+			GCDBG(GCZONE_DEST, "  physical descriptor = 0x%08X\n",
+			      bvphysdesc);
+			GCDBG(GCZONE_DEST, "  first page = 0x%08X\n",
+			      bvphysdesc->pagearray[0]);
+			GCDBG(GCZONE_DEST, "  page offset = 0x%08X\n",
+			      bvphysdesc->pageoffset);
+		} else {
+			GCDBG(GCZONE_DEST, "  virtual address = 0x%08X\n",
+			      (unsigned int) dstinfo->buf.desc->virtaddr);
+		}
+
+		GCDBG(GCZONE_DEST, "  stride = %ld\n",
+		      dstinfo->stride1);
+		GCDBG(GCZONE_DEST, "  geometry size = %dx%d\n",
+		      dstinfo->width, dstinfo->height);
+		GCDBG(GCZONE_DEST, "  surface offset (pixels) = %d,%d\n",
+		      dstinfo->xpixalign, dstinfo->ypixalign);
+		GCDBG(GCZONE_DEST, "  surface offset (bytes) = %d\n",
+		      dstinfo->bytealign1);
+
+		/* Check for unsupported dest formats. */
+		if ((dstinfo->format.type == BVFMT_YUV) &&
+		    (dstinfo->format.cs.yuv.planecount > 1)) {
+			BVSETBLTERROR(BVERR_DSTGEOM_FORMAT,
+				      "destination format unsupported");
+			goto exit;
+		}
+
+		/* Zero-fill for destination is not supported. */
+		if (dstinfo->format.zerofill) {
+			BVSETBLTERROR(BVERR_DSTGEOM_FORMAT,
+				      "0 filling is not supported.");
+			goto exit;
+		}
+
+		/* Validate the stride. */
+		bverror = valid_stride(bvbltparams, dstinfo);
+		if (bverror != BVERR_NONE)
+			goto exit;
+
+		/* Validate geometry. */
+		if (!valid_geom(dstinfo)) {
+			BVSETBLTERROR(BVERR_DSTGEOM,
+				      "destination geom exceeds surface size");
+			goto exit;
+		}
+	}
+
+	/* Did clipping/destination rects change? */
+	if (dstinfo->rectdirty) {
+		struct gcrect cliprect;
+		struct gcrect *clipdelta;
+
+		/* Get shortcuts to the destination rectangles. */
+		clipdelta = &batch->clipdelta;
+		dstorig = &dstinfo->rect.orig;
+		dstclip = &dstinfo->rect.clip;
+
+		/* Determine destination rectangle. */
+		GCCONVERT_RECT(GCZONE_DEST,
+			       "  rect",
+			       &bvbltparams->dstrect,
+			       dstorig);
+
+		/* Determine whether aux destination is specified. */
+		dstinfo->haveaux
+			= ((bvbltparams->flags & BVFLAG_SRC2_AUXDSTRECT) != 0);
+		GCDBG(GCZONE_DEST, "  have aux dest = %d\n", dstinfo->haveaux);
+
+		if (dstinfo->haveaux) {
+			dstorigaux = &dstinfo->auxrect.orig;
+			dstclipaux = &dstinfo->auxrect.clip;
+
+			/* Convert the aux rectangle. */
+			GCCONVERT_RECT(GCZONE_DEST,
+					"  aux rect",
+					&bvbltparams->src2auxdstrect,
+					dstorigaux);
+		}
+
+		/* Is clipping rectangle specified? */
+		if ((bvbltparams->flags & BVFLAG_CLIP) == BVFLAG_CLIP) {
+			/* Convert the clipping rectangle. */
+			GCCONVERT_RECT(GCZONE_DEST,
+				       "  clipping",
+				       &bvbltparams->cliprect,
+				       &cliprect);
+
+			if ((cliprect.left   < GC_CLIP_RESET_LEFT)  ||
+			    (cliprect.top    < GC_CLIP_RESET_TOP)   ||
+			    (cliprect.right  > GC_CLIP_RESET_RIGHT) ||
+			    (cliprect.bottom > GC_CLIP_RESET_BOTTOM)) {
+				BVSETERROR(BVERR_CLIP_RECT,
+					   "clip rect is invalid");
+				goto exit;
+			}
+
+			/* Compute clipping deltas and the adjusted
+			 * destination rect. */
+			if (cliprect.left <= dstorig->left) {
+				clipdelta->left = 0;
+				dstclip->left = dstorig->left;
+			} else {
+				clipdelta->left
+					= cliprect.left - dstorig->left;
+				dstclip->left = cliprect.left;
+			}
+
+			if (cliprect.top <= dstorig->top) {
+				clipdelta->top = 0;
+				dstclip->top = dstorig->top;
+			} else {
+				clipdelta->top
+					= cliprect.top - dstorig->top;
+				dstclip->top = cliprect.top;
+			}
+
+			if (cliprect.right >= dstorig->right) {
+				clipdelta->right = 0;
+				dstclip->right = dstorig->right;
+			} else {
+				clipdelta->right
+					= cliprect.right - dstorig->right;
+				dstclip->right = cliprect.right;
+			}
+
+			if (cliprect.bottom >= dstorig->bottom) {
+				clipdelta->bottom = 0;
+				dstclip->bottom = dstorig->bottom;
+			} else {
+				clipdelta->bottom
+					= cliprect.bottom - dstorig->bottom;
+				dstclip->bottom = cliprect.bottom;
+			}
+
+			/* Clip the aux destination. */
+			if (dstinfo->haveaux) {
+				dstclipaux->left =
+					(cliprect.left <= dstorigaux->left)
+						? dstorigaux->left
+						: cliprect.left;
+
+				dstclipaux->top =
+					(cliprect.top <= dstorigaux->top)
+						? dstorigaux->top
+						: cliprect.top;
+
+				dstclipaux->right =
+					(cliprect.right >= dstorigaux->right)
+						? dstorigaux->right
+						: cliprect.right;
+
+				dstclipaux->bottom =
+					(cliprect.bottom >= dstorigaux->bottom)
+						? dstorigaux->bottom
+						: cliprect.bottom;
+			}
+		} else {
+			clipdelta->left =
+			clipdelta->top =
+			clipdelta->right =
+			clipdelta->bottom = 0;
+
+			*dstclip = *dstorig;
+
+			if (dstinfo->haveaux)
+				*dstclipaux = *dstorigaux;
+		}
+
+		GCPRINT_RECT(GCZONE_DEST, "  clipped dest", dstclip);
+
+		/* Validate the destination rectangle. */
+		if (!valid_rect(dstinfo, dstclip)) {
+			BVSETBLTERROR(BVERR_DSTRECT,
+				      "invalid destination rectangle.");
+			goto exit;
+		}
+
+		if (dstinfo->haveaux) {
+			GCPRINT_RECT(GCZONE_DEST, "  clipped aux dest",
+				     dstclipaux);
+
+			/* Validate the aux destination rectangle. */
+			if (!valid_rect(dstinfo, dstclipaux)) {
+				BVSETBLTERROR(BVERR_DSTRECT,
+					      "invalid aux destination "
+					      "rectangle.");
+				goto exit;
+			}
+
+			/* Disable aux rectangle if empty. */
+			if (null_rect(dstclipaux)) {
+				GCDBG(GCZONE_DEST, "  empty aux dest.\n");
+				dstinfo->haveaux = false;
+			}
+		}
+
+		GCDBG(GCZONE_DEST,
+		      "  clipping delta = (%d,%d)-(%d,%d)\n",
+		      clipdelta->left,
+		      clipdelta->top,
+		      clipdelta->right,
+		      clipdelta->bottom);
+	}
+
+	/* Did clipping/destination rects change? */
+	if (dstinfo->surfdirty || dstinfo->rectdirty)
+		process_rotation(dstinfo);
+
+exit:
+	GCEXITARG(GCZONE_DEST, "bv%s = %d\n",
+		  (bverror == BVERR_NONE) ? "result" : "error", bverror);
+	return bverror;
+}
+
+enum bverror parse_source(struct bvbltparams *bvbltparams,
+			  struct gcbatch *batch,
+			  struct gcsurface *srcinfo,
+			  unsigned int index,
+			  unsigned short rop)
+{
+	enum bverror bverror = BVERR_NONE;
+	struct bvsurfgeom *srcgeom;
+	struct bvrect *srcrect;
+
+	GCENTER(GCZONE_SRC);
+	GCDBG(GCZONE_SRC, "parsing source #%d\n", index);
+
+	if (index == 0) {
+		/* Set source index. */
+		srcinfo->index = 0;
+
+		/* Determine change flags. */
+		srcinfo->surfdirty = ((batch->batchflags
+				   & BVBATCH_SRC1) != 0);
+		srcinfo->rectdirty = ((batch->batchflags
+				   & BVBATCH_SRC1RECT) != 0);
+
+		/* Set buffer descriptor. */
+		srcinfo->buf = bvbltparams->src1;
+
+		/* Fetch proper structures. */
+		srcgeom = bvbltparams->src1geom;
+		srcrect = &bvbltparams->src1rect;
+	} else {
+		/* Set source index. */
+		srcinfo->index = 1;
+
+		/* Determine change flags. */
+		srcinfo->surfdirty = ((batch->batchflags
+				   & BVBATCH_SRC2) != 0);
+		srcinfo->rectdirty = ((batch->batchflags
+				   & BVBATCH_SRC2RECT) != 0);
+
+		/* Set buffer descriptor. */
+		srcinfo->buf = bvbltparams->src2;
+
+		/* Fetch proper structures. */
+		srcgeom = bvbltparams->src2geom;
+		srcrect = &bvbltparams->src2rect;
+	}
+
+	/* Set parameters. */
+	srcinfo->width = srcgeom->width;
+	srcinfo->height = srcgeom->height;
+	srcinfo->stride1 = srcgeom->virtstride;
+	srcinfo->rop = rop;
+	srcinfo->haveaux = false;
+
+	/* Parse the source format. */
+	if (parse_format(bvbltparams, srcgeom->format,
+			 &srcinfo->format) != BVERR_NONE) {
+		bverror = (index == 0)
+			? BVERR_SRC1GEOM_FORMAT
+			: BVERR_SRC2GEOM_FORMAT;
+		goto exit;
+	}
+
+	/* Parse orientation. */
+	srcinfo->angle = get_angle(srcgeom->orientation);
+	if (srcinfo->angle == ROT_ANGLE_INVALID) {
+		BVSETBLTERROR((index == 0)
+					? BVERR_SRC1GEOM
+					: BVERR_SRC2GEOM,
+			      "unsupported source%d orientation %d.",
+			      index + 1,
+			      srcgeom->orientation);
+		goto exit;
+	}
+
+	/* Assume that the source rotation is supported and the source
+	 * does not need to be software rotared. */
+	srcinfo->adjangle = 0;
+
+	/* Determine source mirror. */
+	srcinfo->mirror = (index == 0)
+			? (bvbltparams->flags >> BVFLAG_FLIP_SRC1_SHIFT)
+			   & BVFLAG_FLIP_MASK
+			: (bvbltparams->flags >> BVFLAG_FLIP_SRC2_SHIFT)
+			   & BVFLAG_FLIP_MASK;
+
+	GCDBG(GCZONE_SRC, "  buffer length = %d\n", srcinfo->buf.desc->length);
+	GCDBG(GCZONE_SRC, "  rotation %d degrees.\n", srcinfo->angle * 90);
+
+	if (srcinfo->buf.desc->auxtype == BVAT_PHYSDESC) {
+		struct bvphysdesc *bvphysdesc;
+		bvphysdesc = (struct bvphysdesc *) srcinfo->buf.desc->auxptr;
+		GCDBG(GCZONE_SRC, "  physical descriptor = 0x%08X\n",
+		      bvphysdesc);
+		GCDBG(GCZONE_SRC, "  first page = 0x%08X\n",
+		      bvphysdesc->pagearray[0]);
+		GCDBG(GCZONE_SRC, "  page offset = 0x%08X\n",
+		      bvphysdesc->pageoffset);
+	} else {
+		GCDBG(GCZONE_SRC, "  virtual address = 0x%08X\n",
+			(unsigned int) srcinfo->buf.desc->virtaddr);
+	}
+
+	GCDBG(GCZONE_SRC, "  stride = %ld\n",
+	      srcinfo->stride1);
+	GCDBG(GCZONE_SRC, "  geometry size = %dx%d\n",
+	      srcinfo->width, srcinfo->height);
+	GCDBG(GCZONE_SRC, "  mirror = %d\n", srcinfo->mirror);
+
+	/* Convert the rectangle. */
+	GCCONVERT_RECT(GCZONE_SRC,
+		       "  rect", srcrect, &srcinfo->rect.orig);
+
+	/* Planar YUV? */
+	if ((srcinfo->format.type == BVFMT_YUV) &&
+	    (srcinfo->format.cs.yuv.planecount > 1)) {
+		int xpixalign;
+
+		/* Source rotation is not supported. */
+		if (srcinfo->angle != ROT_ANGLE_0) {
+			srcinfo->adjangle = (4 - srcinfo->angle) % 4;
+			GCDBG(GCZONE_SRC, "  rotation adjustment angle %d.\n",
+			      srcinfo->adjangle * 90);
+		}
+
+		/* Check base address alignment. */
+		xpixalign = get_pixel_offset(srcinfo, 0);
+		if (xpixalign != 0) {
+			BVSETBLTERROR((index == 0)
+						? BVERR_SRC1DESC_ALIGNMENT
+						: BVERR_SRC2DESC_ALIGNMENT,
+				      "planar YUV base address must be "
+				      "64 byte aligned.");
+			goto exit;
+		}
+	}
+
+	/* Validate the stride. */
+	bverror = valid_stride(bvbltparams, srcinfo);
+	if (bverror != BVERR_NONE)
+		goto exit;
+
+	/* Validate source geometry. */
+	if (!valid_geom(srcinfo)) {
+		BVSETBLTERROR((index == 0)
+					? BVERR_SRC1GEOM
+					: BVERR_SRC2GEOM,
+			      "source%d geom exceeds surface size.",
+			      index + 1);
+		goto exit;
+	}
+
+exit:
+	GCEXITARG(GCZONE_SRC, "bv%s = %d\n",
+		  (bverror == BVERR_NONE) ? "result" : "error", bverror);
+	return bverror;
+}
+
+static enum bverror parse_implicitscale(struct bvbltparams *bvbltparams,
+					struct gcbatch *batch)
+{
+	enum bverror bverror = BVERR_NONE;
+	unsigned int quality;
+	unsigned int technique;
+	unsigned int imagetype;
+
+	GCENTER(GCZONE_SCALING);
+
+	quality = (bvbltparams->scalemode & BVSCALEDEF_QUALITY_MASK)
+		>> BVSCALEDEF_QUALITY_SHIFT;
+	technique = (bvbltparams->scalemode & BVSCALEDEF_TECHNIQUE_MASK)
+		  >> BVSCALEDEF_TECHNIQUE_SHIFT;
+	imagetype = (bvbltparams->scalemode & BVSCALEDEF_TYPE_MASK)
+		  >> BVSCALEDEF_TYPE_SHIFT;
+
+	GCDBG(GCZONE_SCALING, "quality = %d\n", quality);
+	GCDBG(GCZONE_SCALING, "technique = %d\n", technique);
+	GCDBG(GCZONE_SCALING, "imagetype = %d\n", imagetype);
+
+	switch (quality) {
+	case BVSCALEDEF_FASTEST >> BVSCALEDEF_QUALITY_SHIFT:
+		batch->op.filter.horkernelsize = 3;
+		batch->op.filter.verkernelsize = 3;
+		break;
+
+	case BVSCALEDEF_GOOD >> BVSCALEDEF_QUALITY_SHIFT:
+		batch->op.filter.horkernelsize = 5;
+		batch->op.filter.verkernelsize = 5;
+		break;
+
+	case BVSCALEDEF_BETTER >> BVSCALEDEF_QUALITY_SHIFT:
+		batch->op.filter.horkernelsize = 7;
+		batch->op.filter.verkernelsize = 7;
+		break;
+
+	case BVSCALEDEF_BEST >> BVSCALEDEF_QUALITY_SHIFT:
+		batch->op.filter.horkernelsize = 9;
+		batch->op.filter.verkernelsize = 9;
+		break;
+
+	default:
+		BVSETBLTERROR(BVERR_SCALE_MODE,
+			      "unsupported scale quality 0x%02X", quality);
+		goto exit;
+	}
+
+	switch (technique) {
+	case BVSCALEDEF_DONT_CARE >> BVSCALEDEF_TECHNIQUE_SHIFT:
+	case BVSCALEDEF_NOT_NEAREST_NEIGHBOR >> BVSCALEDEF_TECHNIQUE_SHIFT:
+		break;
+
+	case BVSCALEDEF_POINT_SAMPLE >> BVSCALEDEF_TECHNIQUE_SHIFT:
+		batch->op.filter.horkernelsize = 1;
+		batch->op.filter.verkernelsize = 1;
+		break;
+
+	case BVSCALEDEF_INTERPOLATED >> BVSCALEDEF_TECHNIQUE_SHIFT:
+		break;
+
+	default:
+		BVSETBLTERROR(BVERR_SCALE_MODE,
+			      "unsupported scale technique %d", technique);
+		goto exit;
+	}
+
+	switch (imagetype) {
+	case 0:
+	case BVSCALEDEF_PHOTO >> BVSCALEDEF_TYPE_SHIFT:
+	case BVSCALEDEF_DRAWING >> BVSCALEDEF_TYPE_SHIFT:
+		break;
+
+	default:
+		BVSETBLTERROR(BVERR_SCALE_MODE,
+			      "unsupported image type %d", imagetype);
+		goto exit;
+	}
+
+	GCDBG(GCZONE_SCALING, "kernel size = %dx%d\n",
+	      batch->op.filter.horkernelsize,
+	      batch->op.filter.verkernelsize);
+
+exit:
+	GCEXIT(GCZONE_SCALING);
+	return bverror;
+}
+
+static enum bverror parse_explicitscale(struct bvbltparams *bvbltparams,
+					struct gcbatch *batch)
+{
+	enum bverror bverror = BVERR_NONE;
+	unsigned int horsize;
+	unsigned int versize;
+
+	GCENTER(GCZONE_SCALING);
+
+	horsize = (bvbltparams->scalemode & BVSCALEDEF_HORZ_MASK)
+		>> BVSCALEDEF_HORZ_SHIFT;
+	versize = (bvbltparams->scalemode & BVSCALEDEF_VERT_MASK)
+		  >> BVSCALEDEF_VERT_SHIFT;
+
+	GCDBG(GCZONE_SCALING, "horsize = %d\n", horsize);
+	GCDBG(GCZONE_SCALING, "versize = %d\n", versize);
+
+	switch (horsize) {
+	case BVSCALEDEF_NEAREST_NEIGHBOR:
+		batch->op.filter.horkernelsize = 1;
+		break;
+
+	case BVSCALEDEF_LINEAR:
+	case BVSCALEDEF_CUBIC:
+	case BVSCALEDEF_3_TAP:
+		batch->op.filter.horkernelsize = 3;
+		break;
+
+	case BVSCALEDEF_5_TAP:
+		batch->op.filter.horkernelsize = 5;
+		break;
+
+	case BVSCALEDEF_7_TAP:
+		batch->op.filter.horkernelsize = 7;
+		break;
+
+	case BVSCALEDEF_9_TAP:
+		batch->op.filter.horkernelsize = 9;
+		break;
+
+	default:
+		BVSETBLTERROR(BVERR_SCALE_MODE,
+			      "unsupported horizontal kernel size %d", horsize);
+		goto exit;
+	}
+
+	switch (versize) {
+	case BVSCALEDEF_NEAREST_NEIGHBOR:
+		batch->op.filter.verkernelsize = 1;
+		break;
+
+	case BVSCALEDEF_LINEAR:
+	case BVSCALEDEF_CUBIC:
+	case BVSCALEDEF_3_TAP:
+		batch->op.filter.verkernelsize = 3;
+		break;
+
+	case BVSCALEDEF_5_TAP:
+		batch->op.filter.verkernelsize = 5;
+		break;
+
+	case BVSCALEDEF_7_TAP:
+		batch->op.filter.verkernelsize = 7;
+		break;
+
+	case BVSCALEDEF_9_TAP:
+		batch->op.filter.verkernelsize = 9;
+		break;
+
+	default:
+		BVSETBLTERROR(BVERR_SCALE_MODE,
+			      "unsupported vertical kernel size %d", versize);
+		goto exit;
+	}
+
+	GCDBG(GCZONE_SCALING, "kernel size = %dx%d\n",
+	      batch->op.filter.horkernelsize,
+	      batch->op.filter.verkernelsize);
+
+exit:
+	GCEXIT(GCZONE_SCALING);
+	return bverror;
+}
+
+enum bverror parse_scalemode(struct bvbltparams *bvbltparams,
+			     struct gcbatch *batch)
+{
+	enum bverror bverror;
+	unsigned int scaleclass;
+
+	GCENTER(GCZONE_SCALING);
+
+	scaleclass = (bvbltparams->scalemode & BVSCALEDEF_CLASS_MASK)
+		   >> BVSCALEDEF_CLASS_SHIFT;
+
+	GCDBG(GCZONE_SCALING, "scaleclass = %d\n", scaleclass);
+
+	switch (scaleclass) {
+	case BVSCALEDEF_IMPLICIT >> BVSCALEDEF_CLASS_SHIFT:
+		bverror = parse_implicitscale(bvbltparams, batch);
+		break;
+
+	case BVSCALEDEF_EXPLICIT >> BVSCALEDEF_CLASS_SHIFT:
+		bverror = parse_explicitscale(bvbltparams, batch);
+		break;
+
+	default:
+		BVSETBLTERROR(BVERR_SCALE_MODE,
+			      "unsupported scale class %d", scaleclass);
+		goto exit;
+	}
+
+exit:
+	GCEXIT(GCZONE_SCALING);
+	return bverror;
+}
diff --git a/drivers/misc/gcx/gccore/Kconfig b/drivers/misc/gcx/gccore/Kconfig
new file mode 100644
index 0000000..060f9be
--- /dev/null
+++ b/drivers/misc/gcx/gccore/Kconfig
@@ -0,0 +1,5 @@
+config GCCORE
+	tristate "Vivante Core Driver"
+	default y
+	help
+           Vivante Core Driver.
diff --git a/drivers/misc/gcx/gccore/Makefile b/drivers/misc/gcx/gccore/Makefile
new file mode 100644
index 0000000..9e76c2c
--- /dev/null
+++ b/drivers/misc/gcx/gccore/Makefile
@@ -0,0 +1,9 @@
+obj-$(CONFIG_GCCORE) += gccore.o
+
+gccore-y := \
+	gcmain.o \
+	gcmem.o \
+	gcmmu.o \
+	gcqueue.o \
+	gcdebug.o \
+	gcdbglog.o
diff --git a/drivers/misc/gcx/gccore/gcdbglog.c b/drivers/misc/gcx/gccore/gcdbglog.c
new file mode 100644
index 0000000..4ee6744
--- /dev/null
+++ b/drivers/misc/gcx/gccore/gcdbglog.c
@@ -0,0 +1,2325 @@
+/*
+ * gcdbglog.c
+ *
+ * Copyright (C) 2010-2011 Vivante Corporation.
+ *
+ * This package is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#include <linux/module.h>
+#include <linux/device.h>
+#include <linux/slab.h>
+#include <linux/fs.h>
+#include <linux/io.h>
+#include <linux/sched.h>
+#include <linux/ioctl.h>
+#include <linux/clk.h>
+#include <linux/seq_file.h>
+#include <linux/kernel.h>
+#include <stdarg.h>
+#include <linux/gcreg.h>
+#include <linux/gcx.h>
+#include "gcmain.h"
+
+#if GCDEBUG_ENABLE
+
+/*******************************************************************************
+ * Debug switches.
+ */
+
+/* Dumping enable default state. */
+#define GC_DUMP_ENABLE		0
+
+/* Ignore all zones as if they were all enabled in all modules. */
+#define GC_IGNORE_ZONES		0
+
+/* When enabled, all output is collected into a buffer with a predefined size.
+ * GC_DUMP_BUFFER_SIZE determines the size of the buffer and GC_ENABLE_OVERFLOW
+ * controls what happens when the buffer gets full. */
+#define GC_BUFFERED_OUTPUT	0
+
+/* Debug output buffer size. */
+#define GC_DUMP_BUFFER_SIZE	(400 * 1024)
+
+/* If disabled, the contents of the buffer will be dumped to the console when
+ * the buffer gets full.
+ * If enabled, wrap around mode is enabled where when the buffer gets full,
+ * the oldest entries are overwritten with the new entrie. To dump the buffer
+ * to the console gc_dump_flush must be called explicitly. */
+#define GC_ENABLE_OVERFLOW	1
+
+/* Specifies how many prints are accumulated in the buffer before the buffer is
+ * flushed. Set to zero to disable auto dumping mode. */
+#define GC_FLUSH_COUNT		0
+
+/* Specifies the maximum number of threads that will be tracked in an attempt
+ * to visually separate messages from different threads. To disable thread
+ * tracking, set to 0 or 1. */
+#define GC_THREAD_COUNT		20
+
+/* Specifies spacing for thread messages. */
+#define GC_THREAD_INDENT	0
+
+/* Print the timestamp. */
+#define GC_SHOW_TIME		1
+
+/* When set to non-zero, specifies how many prints are accumulated in the
+ * buffer before the buffer is flushed. */
+#define GC_SHOW_DUMP_LINE	1
+
+/* If enabled, each print statement will be preceeded with the current
+ * process ID. */
+#define GC_SHOW_PID		1
+
+/* If enabled, internal logging validation code is turned on. */
+#define GC_DEBUG_SELF		0
+
+/* Maximum length of a dump string. */
+#define GC_MAXSTR_LENGTH	256
+
+/* Print buffers like C arrays. */
+#define GC_C_BUFFER		0
+
+
+/*******************************************************************************
+ * Miscellaneous macros.
+ */
+
+#define GC_PTRALIGNMENT(p, alignment) \
+( \
+	GC_ALIGN(GC_PTR2INT(p), alignment) - GC_PTR2INT(p) \
+)
+
+#define GC_VARARG_ALIGNMENT sizeof(unsigned long long)
+
+#if defined(GCDBGFILTER)
+#undef GCDBGFILTER
+#endif
+
+#define GCDBGFILTER \
+	(*filter)
+
+#if GC_IGNORE_ZONES
+#define GC_VERIFY_ENABLE(filter, zone) \
+	(g_initdone)
+#else
+#define GC_VERIFY_ENABLE(filter, zone) \
+	(g_initdone && ((filter == NULL) || ((filter->zone & zone) != 0)))
+#endif
+
+#if GC_SHOW_TIME
+#define GC_TIME_FORMAT "[%5ld.%10ld] "
+#endif
+
+#if GC_SHOW_DUMP_LINE
+#define GC_DUMPLINE_FORMAT "[%12d] "
+#endif
+
+#if GC_SHOW_PID
+#define GC_PID_FORMAT "[pid=%04X] "
+#endif
+
+#define GC_EOL_RESERVE 1
+
+/*******************************************************************************
+ * Dump item header definition.
+ */
+
+enum itemtype {
+	GC_BUFITEM_NONE,
+	GC_BUFITEM_STRING,
+	GC_BUFITEM_BUFFER
+};
+
+/* Common item head/buffer terminator. */
+struct itemhead {
+	enum itemtype type;
+};
+
+
+/*******************************************************************************
+ * Supported dump items.
+ */
+
+/* GC_BUFITEM_STRING: buffered string. */
+struct itemstring {
+	enum itemtype itemtype;
+	int indent;
+
+#if GC_SHOW_TIME
+	struct timespec timestamp;
+#endif
+
+#if GC_SHOW_DUMP_LINE
+	unsigned int dumpline;
+#endif
+
+#if GC_SHOW_PID
+	struct task_struct *task;
+#endif
+
+	const char *message;
+	va_list messagedata;
+	unsigned int datasize;
+};
+
+/* GC_BUFITEM_BUFFER: buffered memory. */
+enum buffertype {
+	GC_BUFTYPE_GENERIC,
+	GC_BUFTYPE_COMMAND,
+	GC_BUFTYPE_SURFACE
+};
+
+#define GC_GENERIC_DATA_COUNT 32
+#define GC_SURFACE_DATA_COUNT 64
+
+struct itembuffer {
+	enum itemtype itemtype;
+	enum buffertype buffertype;
+	int indent;
+
+	unsigned int surfwidth;
+	unsigned int surfheight;
+	unsigned int surfbpp;
+	unsigned int x1, y1;
+	unsigned int x2, y2;
+
+	unsigned int datasize;
+	unsigned int gpuaddr;
+};
+
+
+/*******************************************************************************
+ * Debug output buffer.
+ */
+
+struct threadinfo {
+	struct task_struct *task;
+	int msgindent;
+	int threadindent;
+};
+
+struct buffout {
+	int enable;
+
+#if GC_THREAD_COUNT > 1
+	unsigned int threadcount;
+	struct threadinfo threadinfo[1 + GC_THREAD_COUNT];
+#else
+	struct threadinfo threadinfo[1];
+#endif
+
+#if GC_SHOW_DUMP_LINE
+	unsigned int dumpline;
+#endif
+
+#if GC_BUFFERED_OUTPUT
+	int start;
+	int index;
+	int count;
+	unsigned char *buffer;
+#endif
+};
+
+static struct buffout g_outputbuffer = {
+	.enable = GC_DUMP_ENABLE
+};
+
+
+/*******************************************************************************
+ * Internal structures.
+ */
+
+struct copypos {
+	struct gcmmustlb *slave;
+	union gcmmuloc pos;
+	unsigned int physical;
+	unsigned char *logical;
+};
+
+
+/*******************************************************************************
+ * Globals.
+ */
+
+static bool g_initdone;
+static DEFINE_MUTEX(g_lockmutex);
+static struct list_head gc_filterlist = LIST_HEAD_INIT(gc_filterlist);
+
+
+/*******************************************************************************
+ * Item size functions.
+ */
+
+#if GC_BUFFERED_OUTPUT
+static int get_item_size_terminator(struct itemhead *item)
+{
+	return sizeof(struct itemhead);
+}
+
+static int get_item_size_string(struct itemhead *item)
+{
+	struct itemstring *itemstring = (struct itemstring *) item;
+	unsigned int vlen = *((unsigned char **) &itemstring->messagedata)
+					- ((unsigned char *) itemstring);
+	return vlen + itemstring->datasize;
+}
+
+static int get_item_size_buffer(struct itemhead *item)
+{
+	struct itembuffer *itembuffer = (struct itembuffer *) item;
+	return sizeof(struct itembuffer) + itembuffer->datasize;
+}
+
+#if GC_ENABLE_OVERFLOW
+typedef int (*getitemsize) (struct itemhead *item);
+
+static getitemsize g_itemsize[] = {
+	get_item_size_terminator,
+	get_item_size_string,
+	get_item_size_buffer
+};
+#endif
+#endif
+
+
+/*******************************************************************************
+ * Printing functions.
+ */
+
+#define GC_PRINTK(s, fmt, ...) \
+do { \
+	if (s) \
+		seq_printf(s, fmt, ##__VA_ARGS__); \
+	else \
+		printk(KERN_INFO fmt, ##__VA_ARGS__); \
+} while (0)
+
+#if GC_DEBUG_SELF
+#	define GC_DEBUGMSG(fmt, ...) \
+		GC_PRINTK(NULL, "[%s:%d] " fmt, __func__, __LINE__, \
+			  ##__VA_ARGS__)
+#else
+#	define GC_DEBUGMSG(...)
+#endif
+
+static struct threadinfo *get_threadinfo(struct buffout *buffout)
+{
+#if GC_THREAD_COUNT > 1
+	struct threadinfo *threadinfo;
+	struct task_struct *task;
+	unsigned int i, count;
+
+	/* Get current task. */
+	task = current;
+
+	/* Try to locate task record. */
+	count = buffout->threadcount + 1;
+	for (i = 1; i < count; i += 1)
+		if (buffout->threadinfo[i].task == task)
+			return &buffout->threadinfo[i];
+
+	/* Not found, still have room? */
+	if (buffout->threadcount < GC_THREAD_COUNT) {
+		threadinfo = &buffout->threadinfo[count];
+		threadinfo->task = task;
+		threadinfo->msgindent = 0;
+		threadinfo->threadindent = buffout->threadcount
+					 * GC_THREAD_INDENT;
+		buffout->threadcount += 1;
+		return threadinfo;
+	}
+
+	/* Too many threads, use the common entry. */
+	GC_PRINTK(NULL, "%s(%d) [ERROR] reached the maximum thread number.\n",
+		  __func__, __LINE__);
+	threadinfo = buffout->threadinfo;
+	threadinfo->task = task;
+	return threadinfo;
+#else
+	struct threadinfo *threadinfo;
+	threadinfo = buffout->threadinfo;
+
+#if GC_SHOW_PID
+	threadinfo->task = current;
+#else
+	threadinfo->task = NULL;
+#endif
+
+	return threadinfo;
+#endif
+}
+
+static int gc_get_indent(int indent, char *buffer, int buffersize)
+{
+	static const int MAX_INDENT = 80;
+	int len, _indent;
+
+	_indent = indent % MAX_INDENT;
+	if (_indent > buffersize)
+		_indent = buffersize - 1;
+
+	for (len = 0; len < _indent; len += 1)
+		buffer[len] = ' ';
+
+	buffer[len] = '\0';
+	return len;
+}
+
+static void gc_print_string(struct seq_file *s, struct itemstring *str)
+{
+	int len = 0;
+	char buffer[GC_MAXSTR_LENGTH];
+
+#if GC_SHOW_TIME
+	len += snprintf(buffer + len, sizeof(buffer) - len - GC_EOL_RESERVE,
+			GC_TIME_FORMAT,
+			str->timestamp.tv_sec,
+			str->timestamp.tv_nsec);
+#endif
+
+#if GC_SHOW_DUMP_LINE
+	len += snprintf(buffer + len, sizeof(buffer) - len - GC_EOL_RESERVE,
+			GC_DUMPLINE_FORMAT, str->dumpline);
+#endif
+
+#if GC_SHOW_PID
+	len += snprintf(buffer + len, sizeof(buffer) - len - GC_EOL_RESERVE,
+			GC_PID_FORMAT, task_pid_vnr(str->task));
+#endif
+
+	/* Append the indent string. */
+	len += gc_get_indent(str->indent, buffer + len,
+			     sizeof(buffer) - len - GC_EOL_RESERVE);
+
+	/* Format the string. */
+	len += vsnprintf(buffer + len, sizeof(buffer) - len - GC_EOL_RESERVE,
+			 str->message, str->messagedata);
+
+	/* Add end-of-line if missing. */
+	if (buffer[len - 1] != '\n')
+		buffer[len++] = '\n';
+	buffer[len] = '\0';
+
+	/* Print the string. */
+	GC_PRINTK(s, "%s", buffer);
+
+	/* Notify the OS that we are still alive. */
+	touch_softlockup_watchdog();
+}
+
+static void gc_print_generic(struct seq_file *s, struct itembuffer *item,
+			     unsigned char *data)
+{
+	char buffer[GC_MAXSTR_LENGTH];
+	unsigned int i, indent, len;
+
+	/* Append the indent string. */
+	indent = gc_get_indent(item->indent, buffer, sizeof(buffer));
+
+	/* Print the title. */
+	GC_PRINTK(s, "%sBUFFER @ 0x%08X (0x%08X)\n",
+		  buffer, item->gpuaddr, (unsigned int) data);
+
+	/* Notify the OS that we are still alive. */
+	touch_softlockup_watchdog();
+
+	/* Print the buffer. */
+	for (i = 0, len = indent; i < item->datasize; i += 4) {
+		if ((i % GC_GENERIC_DATA_COUNT) == 0) {
+			if (i != 0) {
+				/* Print the string. */
+				GC_PRINTK(s, "%s\n", buffer);
+
+				/* Notify the OS that we are still alive. */
+				touch_softlockup_watchdog();
+
+				/* Reset the line. */
+				len = indent;
+			}
+
+			len += snprintf(buffer + len, sizeof(buffer) - len,
+					"0x%08X: ", item->gpuaddr + i);
+		}
+
+		/* Append the data value. */
+		len += snprintf(buffer + len, sizeof(buffer) - len,
+				" 0x%08X", *(unsigned int *) (data + i));
+	}
+
+	/* Print the last partial string. */
+	if ((i % GC_SURFACE_DATA_COUNT) != 0)
+		GC_PRINTK(s, "%s\n", buffer);
+}
+
+static char *gc_module_name(unsigned int index)
+{
+	switch (index) {
+	case GCREG_COMMAND_STALL_STALL_SOURCE_FRONT_END:
+		return "FE";
+
+	case GCREG_COMMAND_STALL_STALL_SOURCE_PIXEL_ENGINE:
+		return "PE";
+
+	case GCREG_COMMAND_STALL_STALL_SOURCE_DRAWING_ENGINE:
+		return "DE";
+
+	default:
+		return "*INVALID*";
+	}
+}
+
+static void gc_print_command(struct seq_file *s, struct itembuffer *item,
+			     unsigned char *data)
+{
+	char buffer[GC_MAXSTR_LENGTH];
+	unsigned int *data32;
+	unsigned int i, j, datacount;
+	unsigned int command, count, addr;
+	unsigned int delay, src, dst;
+	unsigned int x1, y1, x2, y2;
+
+	/* Append the indent string. */
+	gc_get_indent(item->indent, buffer, sizeof(buffer));
+
+	/* Print the title. */
+	GC_PRINTK(s, "%sCOMMAND BUFFER @ 0x%08X\n", buffer, item->gpuaddr);
+	GC_PRINTK(s, "%s  size = %d\n", buffer, item->datasize);
+
+	datacount = (item->datasize + 3) / 4;
+	data32 = (unsigned int *) data;
+	for (i = 0; i < datacount;) {
+#if GC_C_BUFFER
+		GC_PRINTK(s, "%s\t0x%08X,\n", buffer, data32[i++]);
+#else
+		command = (data32[i] >> 27) & 0x1F;
+
+		switch (command) {
+		case GCREG_COMMAND_OPCODE_LOAD_STATE:
+			count = (data32[i] >> 16) & 0x3FF;
+			addr = data32[i] & 0xFFFF;
+			GC_PRINTK(s, "%s  0x%08X: 0x%08X  STATE(0x%04X, %d)\n",
+				  buffer, item->gpuaddr + (i << 2),
+				  data32[i], addr, count);
+			i += 1;
+
+			count |= 1;
+			for (j = 0; j < count; i += 1, j += 1)
+				GC_PRINTK(s, "%s%14c0x%08X\n",
+					  buffer, ' ', data32[i]);
+			break;
+
+		case GCREG_COMMAND_OPCODE_END:
+			GC_PRINTK(s, "%s  0x%08X: 0x%08X  END()\n",
+				  buffer, item->gpuaddr + (i << 2),
+				  data32[i]);
+			i += 1;
+
+			GC_PRINTK(s, "%s%14c0x%08X\n",
+				  buffer, ' ', data32[i]);
+			i += 1;
+			break;
+
+		case GCREG_COMMAND_OPCODE_NOP:
+			GC_PRINTK(s, "%s  0x%08X: 0x%08X  NOP()\n",
+				  buffer, item->gpuaddr + (i << 2),
+				  data32[i]);
+			i += 1;
+
+			GC_PRINTK(s, "%s"  "%14c0x%08X\n",
+				buffer, ' ', data32[i]);
+			i += 1;
+			break;
+
+		case GCREG_COMMAND_OPCODE_STARTDE:
+			count = (data32[i] >> 8) & 0xFF;
+			GC_PRINTK(s, "%s  0x%08X: 0x%08X  STARTDE(%d)\n",
+				  buffer, item->gpuaddr + (i << 2),
+				  data32[i], count);
+			i += 1;
+
+			GC_PRINTK(s, "%s"  "%14c0x%08X\n",
+				buffer, ' ', data32[i]);
+			i += 1;
+
+			for (j = 0; j < count; j += 1) {
+				x1 =  data32[i]	       & 0xFFFF;
+				y1 = (data32[i] >> 16) & 0xFFFF;
+				GC_PRINTK(s, "%s%14c0x%08X	 LT(%d,%d)\n",
+					  buffer, ' ', data32[i], x1, y1);
+				i += 1;
+
+				x2 =  data32[i]	       & 0xFFFF;
+				y2 = (data32[i] >> 16) & 0xFFFF;
+				GC_PRINTK(s, "%s%14c0x%08X	 RB(%d,%d)\n",
+					  buffer, ' ', data32[i], x2, y2);
+				i += 1;
+			}
+			break;
+
+		case GCREG_COMMAND_OPCODE_WAIT:
+			delay = data32[i] & 0xFFFF;
+			GC_PRINTK(s, "%s  0x%08X: 0x%08X  WAIT(%d)\n",
+				  buffer, item->gpuaddr + (i << 2),
+				  data32[i], delay);
+			i += 1;
+
+			GC_PRINTK(s, "%s%14c0x%08X\n", buffer, ' ', data32[i]);
+			i += 1;
+			break;
+
+		case GCREG_COMMAND_OPCODE_LINK:
+			count = data32[i] & 0xFFFF;
+			addr = data32[i + 1];
+			GC_PRINTK(s, "%s  0x%08X: 0x%08X  "
+				  "LINK(0x%08X-0x%08X, %d)\n",
+				  buffer, item->gpuaddr + (i << 2),
+				  data32[i], addr, addr + count * 8,
+				  count);
+			i += 1;
+
+			GC_PRINTK(s, "%s%14c0x%08X\n", buffer, ' ', data32[i]);
+			i += 1;
+			break;
+
+		case GCREG_COMMAND_OPCODE_STALL:
+			src =  data32[i + 1]	   & 0x1F;
+			dst = (data32[i + 1] >> 8) & 0x1F;
+
+			GC_PRINTK(s, "%s  0x%08X: 0x%08X  STALL(%s-%s)\n",
+				  buffer, item->gpuaddr + (i << 2),
+				  data32[i],
+				  gc_module_name(src),
+				  gc_module_name(dst));
+			i += 1;
+
+			GC_PRINTK(s, "%s"  "%14c0x%08X\n",
+				  buffer, ' ', data32[i]);
+			i += 1;
+			break;
+
+		default:
+			GC_PRINTK(s, "%s  0x%08X: 0x%08X  UNKNOWN COMMAND\n",
+				  buffer, item->gpuaddr + (i << 2),
+				  data32[i]);
+			i += 2;
+		}
+#endif
+	}
+}
+
+static void gc_flush_line(struct seq_file *s, char *buffer,
+			  unsigned int indent, unsigned int *len,
+			  unsigned int count, unsigned char checksum)
+{
+	unsigned int _len;
+	char countstr[10];
+
+	/* Correct data count. */
+	count %= GC_SURFACE_DATA_COUNT;
+	if (count == 0)
+		count = GC_SURFACE_DATA_COUNT;
+
+	snprintf(countstr, sizeof(countstr), "%02X", count);
+	buffer[indent + 1] = countstr[0];
+	buffer[indent + 2] = countstr[1];
+
+	/* Append the checksum. */
+	_len = *len;
+	_len += snprintf(buffer + _len, sizeof(buffer) - _len,
+			 "%02X", checksum);
+
+	/* Print the string. */
+	GC_PRINTK(s, "%s\n", buffer);
+
+	/* Notify the OS that we are still alive. */
+	touch_softlockup_watchdog();
+
+	/* Reset the length. */
+	*len = indent;
+}
+
+static void gc_print_surface(struct seq_file *s, struct itembuffer *itembuffer,
+			     unsigned char *data)
+{
+	char buffer[GC_MAXSTR_LENGTH];
+	unsigned int i, indent, len;
+	unsigned int prevupper32 = ~0U;
+	unsigned int currupper32;
+	unsigned int offset, address;
+	unsigned int width, height;
+
+	/* Append the indent string. */
+	indent = gc_get_indent(itembuffer->indent, buffer, sizeof(buffer));
+
+	/* Print the title. */
+	GC_PRINTK(s, "%sIMAGE SURFACE @ 0x%08X\n",
+		  buffer, itembuffer->gpuaddr);
+
+	GC_PRINTK(s, "%s  surface size = %dx%d\n",
+		  buffer, itembuffer->surfwidth, itembuffer->surfheight);
+
+	GC_PRINTK(s, "%s  surface colordepth = %d\n",
+		  buffer, itembuffer->surfbpp);
+
+	GC_PRINTK(s, "%s  dumping rectangle = (%d,%d)-(%d,%d)\n",
+		  buffer, itembuffer->x1, itembuffer->y1,
+		  itembuffer->x2, itembuffer->y2);
+
+	/* Notify the OS that we are still alive. */
+	touch_softlockup_watchdog();
+
+	/* Add TGA header. */
+	width  = itembuffer->x2 - itembuffer->x1;
+	height = itembuffer->y2 - itembuffer->y1;
+	GC_PRINTK(s, ":12000000000002000000000000000000"
+		  "%02X%02X%02X%02X%02X2000\n",
+		  (width  & 0xFF), ((width  >> 8) & 0xFF),
+		  (height & 0xFF), ((height >> 8) & 0xFF),
+		  itembuffer->surfbpp * 8);
+
+	/* TGA skip header. */
+	offset = 18;
+
+	/* Print the buffer. */
+	for (i = 0, len = indent; i < itembuffer->datasize; i += 1) {
+		/* Determine the current address. */
+		address = offset + i;
+
+		/* Determine the current higher 16 bits of the address. */
+		currupper32 = address >> 16;
+
+		/* Did it change? */
+		if (currupper32 != prevupper32) {
+			/* Print the previous data if any. */
+			if ((i % GC_SURFACE_DATA_COUNT) != 0)
+				gc_flush_line(s, buffer, indent, &len, i, 0);
+
+			/* Set new upper address. */
+			prevupper32 = currupper32;
+			GC_PRINTK(s, ":02000004%04X00\n", prevupper32);
+
+			/* Add the line prefix. */
+			len += snprintf(buffer + len,
+					sizeof(buffer) - len - 2,
+					":xx%04X00", address & 0xFFFF);
+		} else if ((i % GC_SURFACE_DATA_COUNT) == 0) {
+			len += snprintf(buffer + len,
+					sizeof(buffer) - len - 2,
+					":xx%04X00", address & 0xFFFF);
+		}
+
+		/* Append the data value. */
+		len += snprintf(buffer + len,
+				sizeof(buffer) - len - 2,
+				"%02X", data[i]);
+
+		/* End of line? */
+		if (((i + 1) % GC_SURFACE_DATA_COUNT) == 0)
+			gc_flush_line(s, buffer, indent, &len, i + 1, 0);
+	}
+
+	/* Print the last partial string. */
+	if ((i % GC_SURFACE_DATA_COUNT) != 0)
+		gc_flush_line(s, buffer, indent, &len, i, 0);
+
+	/* End of dump. */
+	GC_PRINTK(s, ":00000001FF\n");
+}
+
+typedef void (*printbuffer) (struct seq_file *s, struct itembuffer *itembuffer,
+			     unsigned char *data);
+
+static printbuffer g_printbuffer[] = {
+	gc_print_generic,
+	gc_print_command,
+	gc_print_surface
+};
+
+static void gc_print_buffer(struct seq_file *s, struct itembuffer *itembuffer,
+			    unsigned char *data)
+{
+	if ((itembuffer->buffertype < 0) ||
+		(itembuffer->buffertype >= countof(g_printbuffer))) {
+		GC_PRINTK(s,  "BUFFER ENTRY 0x%08X\n",
+			  (unsigned int) itembuffer);
+		GC_PRINTK(s,  "INVALID BUFFER TYPE %d\n",
+			  itembuffer->buffertype);
+	} else {
+		g_printbuffer[itembuffer->buffertype](s, itembuffer, data);
+	}
+}
+
+
+/*******************************************************************************
+ * Print function wrappers.
+ */
+
+#if GC_BUFFERED_OUTPUT
+static unsigned int gc_print_none(struct seq_file *s, struct buffout *buffout,
+				  struct itemhead *item)
+{
+	/* Return the size of the node. */
+	return get_item_size_terminator(item);
+}
+
+static unsigned int gc_print_string_wrapper(struct seq_file *s,
+					    struct buffout *buffout,
+					    struct itemhead *item)
+{
+	/* Print the message. */
+	gc_print_string(s, (struct itemstring *) item);
+
+	/* Return the size of the node. */
+	return get_item_size_string(item);
+}
+
+static unsigned int gc_print_buffer_wrapper(struct seq_file *s,
+					    struct buffout *buffout,
+					    struct itemhead *item)
+{
+	unsigned char *data;
+	struct itembuffer *itembuffer = (struct itembuffer *) item;
+
+	/* Compute data address. */
+	data = (unsigned char *) (itembuffer + 1);
+
+	/* Print the message. */
+	gc_print_buffer(s, (struct itembuffer *) item, data);
+
+	/* Return the size of the node. */
+	return get_item_size_buffer(item);
+}
+
+typedef unsigned int (*printitem) (struct seq_file *s, struct buffout *buffout,
+				   struct itemhead *item);
+
+static printitem g_printarray[] = {
+	gc_print_none,
+	gc_print_string_wrapper,
+	gc_print_buffer_wrapper
+};
+#endif
+
+
+/*******************************************************************************
+ * Private functions.
+ */
+
+unsigned int gc_get_bpp(unsigned int format)
+{
+	unsigned int bpp;
+
+	switch (format) {
+	case GCREG_DE_FORMAT_INDEX8:
+	case GCREG_DE_FORMAT_A8:
+		bpp = 1;
+		break;
+
+	case GCREG_DE_FORMAT_X4R4G4B4:
+	case GCREG_DE_FORMAT_A4R4G4B4:
+	case GCREG_DE_FORMAT_X1R5G5B5:
+	case GCREG_DE_FORMAT_A1R5G5B5:
+	case GCREG_DE_FORMAT_R5G6B5:
+	case GCREG_DE_FORMAT_YUY2:
+	case GCREG_DE_FORMAT_UYVY:
+	case GCREG_DE_FORMAT_RG16:
+		bpp = 2;
+		break;
+
+	case GCREG_DE_FORMAT_X8R8G8B8:
+	case GCREG_DE_FORMAT_A8R8G8B8:
+		bpp = 4;
+		break;
+
+	default:
+		bpp = 0;
+	}
+
+	return bpp;
+}
+
+static void *gc_map_data(struct copypos *copypos,
+				unsigned int gpuaddr)
+{
+	union gcmmuloc pos;
+	unsigned int offset;
+	unsigned int physical;
+	unsigned int *stlblogical;
+	void *cpuaddr;
+
+	/* Determine MMU table position. */
+	pos.loc.mtlb = (gpuaddr & GCMMU_MTLB_MASK) >> GCMMU_MTLB_SHIFT;
+	pos.loc.stlb = (gpuaddr & GCMMU_STLB_MASK) >> GCMMU_STLB_SHIFT;
+	offset = gpuaddr & GCMMU_OFFSET_MASK;
+
+	/* Map if not yet mapped. */
+	if (pos.absolute != copypos->pos.absolute) {
+		if (copypos->logical != NULL) {
+			iounmap(copypos->logical);
+			copypos->logical = NULL;
+		}
+
+		if (copypos->physical != ~0U) {
+			release_mem_region(copypos->physical, PAGE_SIZE);
+			copypos->physical = ~0U;
+		}
+
+		stlblogical = copypos->slave[pos.loc.mtlb].logical;
+		if (stlblogical == NULL) {
+			gc_dump_string(NULL, 0,
+					"stlb table %d is not allocated.\n",
+					pos.loc.mtlb);
+			goto exit;
+		}
+
+		physical = stlblogical[pos.loc.stlb] & GCMMU_STLB_ADDRESS_MASK;
+
+		if (!request_mem_region(physical, PAGE_SIZE, "dumpbuffer")) {
+			gc_dump_string(NULL, 0,
+					"request_mem_region failed.\n");
+			goto exit;
+		}
+
+		copypos->physical = physical;
+		copypos->logical = (unsigned char *)
+				ioremap_nocache(copypos->physical, PAGE_SIZE);
+
+		if (copypos->logical == NULL) {
+			gc_dump_string(NULL, 0,
+					"ioremap failed.\n");
+			goto exit;
+		}
+
+		copypos->pos.absolute = pos.absolute;
+	}
+
+	/* Compute the CPU virtual address. */
+	cpuaddr = copypos->logical + offset;
+	return cpuaddr;
+
+exit:;
+	gc_dump_string(NULL, 0,	 "gpuaddr = 0x%08X\n", gpuaddr);
+	gc_dump_string(NULL, 0,	 "mtlb = %d\n", pos.loc.mtlb);
+	gc_dump_string(NULL, 0,	 "stlb = %d\n", pos.loc.stlb);
+	gc_dump_string(NULL, 0,	 "offset = 0x%08X\n", offset);
+	return NULL;
+}
+
+static void gc_copy_generic_buffer(struct gcmmucontext *gcmmucontext,
+					void *dest,
+					struct itembuffer *itembuffer)
+{
+	unsigned int gpuaddr, lastaddr;
+	struct copypos copypos;
+	void *cpuaddr;
+
+	/* Reset memory position structure. */
+	copypos.slave = gcmmucontext->slave;
+	copypos.pos.absolute = ~0U;
+	copypos.physical = ~0U;
+	copypos.logical = NULL;
+
+	/* Compute the last address. */
+	lastaddr = itembuffer->gpuaddr + itembuffer->datasize;
+
+	for (gpuaddr = itembuffer->gpuaddr; gpuaddr < lastaddr; gpuaddr += 4) {
+		cpuaddr = gc_map_data(&copypos, gpuaddr);
+		if (cpuaddr == NULL) {
+			gc_dump_mmu(NULL, 0, gcmmucontext);
+			goto exit;
+		}
+
+		memcpy(dest, cpuaddr, 4);
+		dest = (unsigned char *) dest + 4;
+	}
+
+exit:
+	if (copypos.logical != NULL)
+		iounmap(copypos.logical);
+
+	if (copypos.physical != ~0U)
+		release_mem_region(copypos.physical, PAGE_SIZE);
+}
+
+static void gc_copy_surface(struct gcmmucontext *gcmmucontext, void *dest,
+				struct itembuffer *itembuffer)
+{
+	unsigned int stride;
+	unsigned int x, y;
+	unsigned int lineoffset;
+	unsigned int gpuaddr;
+	struct copypos copypos;
+	void *cpuaddr;
+
+	/* Reset memory position structure. */
+	copypos.slave = gcmmucontext->slave;
+	copypos.pos.absolute = ~0U;
+	copypos.physical = ~0U;
+	copypos.logical = NULL;
+
+	/* Compute the srtride. */
+	stride = itembuffer->surfwidth * itembuffer->surfbpp;
+
+	for (y = itembuffer->y1; y < itembuffer->y2; y += 1) {
+		lineoffset = y * stride;
+
+		for (x = itembuffer->x1; x < itembuffer->x2; x += 1) {
+			/* Compute the address. */
+			gpuaddr = itembuffer->gpuaddr + lineoffset
+				+ x * itembuffer->surfbpp;
+
+			cpuaddr = gc_map_data(&copypos, gpuaddr);
+			if (cpuaddr == NULL) {
+				gc_dump_mmu(NULL, 0, gcmmucontext);
+				goto exit;
+			}
+
+			memcpy(dest, cpuaddr, itembuffer->surfbpp);
+			dest = (unsigned char *) dest + itembuffer->surfbpp;
+		}
+	}
+
+exit:
+	if (copypos.logical != NULL)
+		iounmap(copypos.logical);
+
+	if (copypos.physical != ~0U)
+		release_mem_region(copypos.physical, PAGE_SIZE);
+}
+
+#if GC_BUFFERED_OUTPUT
+static void gc_buffer_flush(struct seq_file *s, struct buffout *buffout)
+{
+	int i, skip;
+	struct itemhead *item;
+
+	if (buffout->count == 0)
+		return;
+
+	GC_PRINTK(s,  "****************************************"
+				"****************************************\n");
+	GC_PRINTK(s,  "FLUSHING DEBUG OUTPUT BUFFER (%d elements).\n",
+				buffout->count);
+
+#if !GC_ENABLE_OVERFLOW
+	{
+		int occupied = (100 * (buffout->index - buffout->start))
+				/ GC_DUMP_BUFFER_SIZE;
+		if (buffout->start != 0)
+			GC_PRINTK(s,  "	 START = %d\n", buffout->start);
+		GC_PRINTK(s,  "	 INDEX = %d\n", buffout->index);
+		GC_PRINTK(s,  "	 BUFFER USE = %d%%\n", occupied);
+	}
+#endif
+
+	GC_PRINTK(s,  "****************************************"
+			   "****************************************\n");
+
+	item = (struct itemhead *) &buffout->buffer[buffout->start];
+	GC_DEBUGMSG("start=%d.\n", buffout->start);
+
+	/* Notify the OS that we are still alive. */
+	touch_softlockup_watchdog();
+
+	for (i = 0; i < buffout->count; i += 1) {
+		GC_DEBUGMSG("printing item %d of type %d @ 0x%08X.\n",
+			    i, item->type, (unsigned int) item);
+		skip = (*g_printarray[item->type]) (s, buffout, item);
+
+		item = (struct itemhead *) ((unsigned char *) item + skip);
+		GC_DEBUGMSG("next item @ 0x%08X.\n", (unsigned int) item);
+
+		if (item->type == GC_BUFITEM_NONE) {
+			GC_DEBUGMSG("reached the end of buffer.\n");
+			item = (struct itemhead *) buffout->buffer;
+		}
+	}
+
+	GC_DEBUGMSG("resetting the buffer.\n");
+	buffout->start = 0;
+	buffout->index = 0;
+	buffout->count = 0;
+
+	/* Notify the OS that we are still alive. */
+	touch_softlockup_watchdog();
+}
+
+static struct itemhead *gc_allocate_item(struct buffout *buffout, int size)
+{
+	struct itemhead *item, *next;
+	int endofbuffer = (buffout->index + size
+			>= GC_DUMP_BUFFER_SIZE - sizeof(struct itemhead));
+
+#if GC_ENABLE_OVERFLOW
+	int skip, bufferoverflow;
+
+	bufferoverflow = (buffout->index < buffout->start) &&
+				(buffout->index + size >= buffout->start);
+
+	if (endofbuffer || bufferoverflow) {
+		if (endofbuffer) {
+			if (buffout->index < buffout->start) {
+				item = (struct itemhead *)
+					&buffout->buffer[buffout->start];
+
+				while (item->type != GC_BUFITEM_NONE) {
+					skip = (*g_itemsize[item->type]) (item);
+
+					buffout->start += skip;
+					buffout->count -= 1;
+
+					item->type = GC_BUFITEM_NONE;
+					item = (struct itemhead *)
+						((unsigned char *) item + skip);
+				}
+
+				buffout->start = 0;
+			}
+
+			buffout->index = 0;
+		}
+
+		item = (struct itemhead *) &buffout->buffer[buffout->start];
+
+		while (buffout->start - buffout->index <= size) {
+			skip = (*g_itemsize[item->type]) (item);
+
+			buffout->start += skip;
+			buffout->count -= 1;
+
+			item->type = GC_BUFITEM_NONE;
+			item = (struct itemhead *)
+				((unsigned char *) item + skip);
+
+			if (item->type == GC_BUFITEM_NONE) {
+				buffout->start = 0;
+				break;
+			}
+		}
+	}
+#else
+	if (endofbuffer) {
+		GC_PRINTK(NULL, "message buffer full; "
+			"forcing message flush.\n\n");
+		gc_buffer_flush(NULL, buffout);
+	}
+#endif
+
+	item = (struct itemhead *) &buffout->buffer[buffout->index];
+
+	buffout->index += size;
+	buffout->count += 1;
+
+	next = (struct itemhead *) ((unsigned char *) item + size);
+	next->type = GC_BUFITEM_NONE;
+
+	return item;
+}
+
+static void gc_append_string(struct buffout *buffout,
+			     struct itemstring *itemstring)
+{
+	unsigned char *messagedata;
+	struct itemstring *item;
+	unsigned int alignment;
+	int size, freesize;
+	int allocsize;
+
+	/* Determine the maximum item size. */
+	allocsize = sizeof(struct itemstring) + itemstring->datasize
+			+ GC_VARARG_ALIGNMENT;
+
+	/* Allocate the item. */
+	item = (struct itemstring *) gc_allocate_item(buffout, allocsize);
+	GC_DEBUGMSG("allocated %d bytes @ 0x%08X.\n",
+		    allocsize, (unsigned int) item);
+
+	/* Compute the initial message data pointer. */
+	messagedata = (unsigned char *) (item + 1);
+
+	/* Align the data pointer as necessary. */
+	alignment = GC_PTRALIGNMENT(messagedata, GC_VARARG_ALIGNMENT);
+	messagedata += alignment;
+	GC_DEBUGMSG("messagedata @ 0x%08X.\n", (unsigned int) messagedata);
+
+	/* Set item data. */
+	item->itemtype = GC_BUFITEM_STRING;
+	item->indent = itemstring->indent;
+	item->message = itemstring->message;
+	item->messagedata = *(va_list *) &messagedata;
+	item->datasize = itemstring->datasize;
+
+#if GC_SHOW_TIME
+	item->timestamp = itemstring->timestamp;
+#endif
+
+#if GC_SHOW_DUMP_LINE
+	item->dumpline = itemstring->dumpline;
+#endif
+
+#if GC_SHOW_PID
+	item->task = itemstring->task;
+#endif
+
+	/* Copy argument value. */
+	if (itemstring->datasize != 0) {
+		GC_DEBUGMSG("copying %d bytes of messagedata.\n",
+			    itemstring->datasize);
+		memcpy(messagedata,
+		       *(unsigned char **) &itemstring->messagedata,
+		       itemstring->datasize);
+	}
+
+	/* Compute the actual node size. */
+	size = sizeof(struct itemstring) + itemstring->datasize + alignment;
+	GC_DEBUGMSG("adjusted item size=%d.\n", size);
+
+	/* Free extra memory if any. */
+	freesize = allocsize - size;
+	GC_DEBUGMSG("freesize=%d.\n", freesize);
+
+	if (freesize != 0) {
+		struct itemhead *next;
+		buffout->index -= freesize;
+		next = (struct itemhead *) ((unsigned char *) item + size);
+		next->type = GC_BUFITEM_NONE;
+	}
+
+#if GC_BUFFERED_OUTPUT && GC_FLUSH_COUNT
+	if (buffout->count >= GC_FLUSH_COUNT) {
+		GC_PRINTK(NULL, "reached %d message count; "
+			"forcing message flush.\n\n", buffout->count);
+		gc_buffer_flush(NULL, buffout);
+	}
+#endif
+}
+
+static void gc_append_buffer(struct gcmmucontext *gcmmucontext,
+				struct buffout *buffout,
+				struct itembuffer *itembuffer,
+				unsigned int *data)
+{
+	struct itembuffer *item;
+	int allocsize;
+
+	/* Determine the item size. */
+	allocsize = sizeof(struct itembuffer) + itembuffer->datasize;
+
+	/* Allocate the item. */
+	item = (struct itembuffer *) gc_allocate_item(buffout, allocsize);
+	GC_DEBUGMSG("allocated %d bytes @ 0x%08X.\n",
+		    allocsize, (unsigned int) item);
+
+	/* Set item data. */
+	*item = *itembuffer;
+
+	/* Copy data. */
+	if (data != NULL) {
+		memcpy(item + 1, data, itembuffer->datasize);
+	} else {
+		switch (itembuffer->buffertype) {
+		case GC_BUFTYPE_GENERIC:
+		case GC_BUFTYPE_COMMAND:
+			gc_copy_generic_buffer(gcmmucontext, item + 1,
+						itembuffer);
+			break;
+
+		case GC_BUFTYPE_SURFACE:
+			gc_copy_surface(gcmmucontext, item + 1, itembuffer);
+			break;
+		}
+	}
+
+#if GC_BUFFERED_OUTPUT && GC_FLUSH_COUNT
+	if (buffout->count >= GC_FLUSH_COUNT) {
+		GC_PRINTK(NULL, "reached %d message count; "
+			"forcing message flush.\n\n", buffout->count);
+		gc_buffer_flush(NULL, buffout);
+	}
+#endif
+}
+#endif
+
+static void gc_print(struct buffout *buffout, unsigned int argsize,
+		     const char *message, va_list args)
+{
+	struct itemstring itemstring;
+	struct threadinfo *threadinfo;
+
+	mutex_lock(&g_lockmutex);
+
+	/* Locate thead entry. */
+	threadinfo = get_threadinfo(buffout);
+
+	/* Form the indent string. */
+	if (strncmp(message, "--", 2) == 0)
+		threadinfo->msgindent -= 2;
+
+	/* Fill in the sructure. */
+	itemstring.itemtype = GC_BUFITEM_STRING;
+	itemstring.indent = threadinfo->msgindent
+			  + threadinfo->threadindent;
+	itemstring.message = message;
+	itemstring.messagedata = args;
+	itemstring.datasize = argsize;
+
+#if GC_SHOW_TIME
+	ktime_get_ts(&itemstring.timestamp);
+#endif
+
+#if GC_SHOW_DUMP_LINE
+	itemstring.dumpline = ++buffout->dumpline;
+#endif
+
+#if GC_SHOW_PID
+	itemstring.task = threadinfo->task;
+#endif
+
+	/* Print the message. */
+#if GC_BUFFERED_OUTPUT
+	gc_append_string(buffout, &itemstring);
+#else
+	gc_print_string(NULL, &itemstring);
+#endif
+
+	/* Check increasing indent. */
+	if (strncmp(message, "++", 2) == 0)
+		threadinfo->msgindent += 2;
+
+	mutex_unlock(&g_lockmutex);
+}
+
+
+/*******************************************************************************
+ * Dumping functions.
+ */
+
+void gc_dump_string(struct gcdbgfilter *filter, unsigned int zone,
+			const char *message, ...)
+{
+	va_list args;
+	unsigned int i, count, argsize;
+
+	if (!g_outputbuffer.enable)
+		return;
+
+	if (message == NULL)
+		GC_DEBUGMSG("message is NULL.\n");
+
+	if (GC_VERIFY_ENABLE(filter, zone)) {
+		for (i = 0, count = 0; message[i]; i += 1)
+			if (message[i] == '%')
+				count += 1;
+
+		argsize = count * sizeof(unsigned int);
+		GC_DEBUGMSG("argsize=%d.\n", argsize);
+
+		va_start(args, message);
+		gc_print(&g_outputbuffer, argsize, message, args);
+		va_end(args);
+	}
+}
+EXPORT_SYMBOL(gc_dump_string);
+
+void gc_dump_string_sized(struct gcdbgfilter *filter, unsigned int zone,
+				unsigned int argsize, const char *message, ...)
+{
+	va_list args;
+
+	if (!g_outputbuffer.enable)
+		return;
+
+	if (GC_VERIFY_ENABLE(filter, zone)) {
+		va_start(args, message);
+		gc_print(&g_outputbuffer, argsize, message, args);
+		va_end(args);
+	}
+}
+EXPORT_SYMBOL(gc_dump_string_sized);
+
+void gc_dump_cmd_buffer(struct gcdbgfilter *filter, unsigned int zone,
+			void *ptr, unsigned int gpuaddr, unsigned int datasize)
+{
+	struct itembuffer itembuffer;
+	struct threadinfo *threadinfo;
+
+	if (!g_outputbuffer.enable)
+		return;
+
+	if (GC_VERIFY_ENABLE(filter, zone)) {
+		mutex_lock(&g_lockmutex);
+
+		/* Locate thead entry. */
+		threadinfo = get_threadinfo(&g_outputbuffer);
+
+		/* Fill in the sructure. */
+		itembuffer.itemtype = GC_BUFITEM_BUFFER;
+		itembuffer.buffertype = GC_BUFTYPE_COMMAND;
+		itembuffer.indent = threadinfo->msgindent
+				  + threadinfo->threadindent;
+		itembuffer.datasize = datasize;
+		itembuffer.gpuaddr = gpuaddr;
+
+		/* Print the message. */
+#if GC_BUFFERED_OUTPUT
+		gc_append_buffer(NULL, &g_outputbuffer, &itembuffer,
+					(unsigned int *) ptr);
+#else
+		gc_print_buffer(NULL, &itembuffer,
+					(unsigned char *) ptr);
+#endif
+
+		mutex_unlock(&g_lockmutex);
+	}
+}
+EXPORT_SYMBOL(gc_dump_cmd_buffer);
+
+void gc_dump_buffer(struct gcdbgfilter *filter, unsigned int zone,
+			void *ptr, unsigned int gpuaddr,
+			unsigned int datasize)
+{
+	struct itembuffer itembuffer;
+	struct threadinfo *threadinfo;
+
+	if (!g_outputbuffer.enable)
+		return;
+
+	if (GC_VERIFY_ENABLE(filter, zone)) {
+		mutex_lock(&g_lockmutex);
+
+		/* Locate thead entry. */
+		threadinfo = get_threadinfo(&g_outputbuffer);
+
+		/* Fill in the sructure. */
+		itembuffer.itemtype = GC_BUFITEM_BUFFER;
+		itembuffer.buffertype = GC_BUFTYPE_GENERIC;
+		itembuffer.indent = threadinfo->msgindent
+				  + threadinfo->threadindent;
+		itembuffer.datasize = datasize;
+		itembuffer.gpuaddr = gpuaddr;
+
+		/* Print the message. */
+#if GC_BUFFERED_OUTPUT
+		gc_append_buffer(NULL, &g_outputbuffer, &itembuffer,
+					(unsigned int *) ptr);
+#else
+		gc_print_buffer(NULL, &itembuffer,
+					(unsigned char *) ptr);
+#endif
+
+		mutex_unlock(&g_lockmutex);
+	}
+}
+EXPORT_SYMBOL(gc_dump_buffer);
+
+void gc_dump_phys_buffer(struct gcdbgfilter *filter, unsigned int zone,
+				struct gcmmucontext *gcmmucontext,
+				unsigned int gpuaddr,
+				unsigned int datasize)
+{
+	struct itembuffer itembuffer;
+	struct threadinfo *threadinfo;
+
+#if !GC_BUFFERED_OUTPUT
+	void *data;
+#endif
+
+	if (!g_outputbuffer.enable)
+		return;
+
+	if (GC_VERIFY_ENABLE(filter, zone)) {
+		mutex_lock(&g_lockmutex);
+
+		/* Locate thead entry. */
+		threadinfo = get_threadinfo(&g_outputbuffer);
+
+		/* Fill in the sructure. */
+		itembuffer.itemtype = GC_BUFITEM_BUFFER;
+		itembuffer.buffertype = GC_BUFTYPE_GENERIC;
+		itembuffer.indent = threadinfo->msgindent
+				  + threadinfo->threadindent;
+		itembuffer.datasize = datasize;
+		itembuffer.gpuaddr = gpuaddr;
+
+		/* Print the message. */
+#if GC_BUFFERED_OUTPUT
+		gc_append_buffer(gcmmucontext, &g_outputbuffer,
+					&itembuffer, NULL);
+#else
+		data = kmalloc(datasize, GFP_KERNEL);
+		if (data != NULL) {
+			gc_copy_generic_buffer(gcmmucontext, data, &itembuffer);
+			gc_print_buffer(NULL, &itembuffer,
+							(unsigned char *) data);
+			kfree(data);
+		}
+#endif
+
+		mutex_unlock(&g_lockmutex);
+	}
+}
+EXPORT_SYMBOL(gc_dump_phys_buffer);
+
+void gc_dump_surface(struct gcdbgfilter *filter, unsigned int zone,
+			void *ptr, unsigned int surfwidth,
+			unsigned int surfheight, unsigned int surfbpp,
+			unsigned int x1, unsigned int y1,
+			unsigned int x2, unsigned int y2,
+			unsigned int gpuaddr)
+{
+	struct itembuffer itembuffer;
+	struct threadinfo *threadinfo;
+	unsigned int datasize;
+
+	if (!g_outputbuffer.enable)
+		return;
+
+	if (GC_VERIFY_ENABLE(filter, zone)) {
+		mutex_lock(&g_lockmutex);
+
+		/* Locate thead entry. */
+		threadinfo = get_threadinfo(&g_outputbuffer);
+
+		/* Compute data size. */
+		datasize = (x2 - x1) * (y2 - y1) * surfbpp;
+
+		/* Fill in the sructure. */
+		itembuffer.itemtype = GC_BUFITEM_BUFFER;
+		itembuffer.buffertype = GC_BUFTYPE_SURFACE;
+		itembuffer.indent = threadinfo->msgindent
+				  + threadinfo->threadindent;
+		itembuffer.surfwidth = surfwidth;
+		itembuffer.surfheight = surfheight;
+		itembuffer.surfbpp = surfbpp;
+		itembuffer.x1 = x1;
+		itembuffer.y1 = y1;
+		itembuffer.x2 = x2;
+		itembuffer.y2 = y2;
+		itembuffer.datasize = datasize;
+		itembuffer.gpuaddr = gpuaddr;
+
+		/* Print the message. */
+#if GC_BUFFERED_OUTPUT
+		gc_append_buffer(NULL, &g_outputbuffer, &itembuffer,
+					(unsigned int *) ptr);
+#else
+		gc_print_buffer(NULL, &itembuffer,
+					(unsigned char *) ptr);
+#endif
+
+		mutex_unlock(&g_lockmutex);
+	}
+}
+EXPORT_SYMBOL(gc_dump_surface);
+
+void gc_dump_phys_surface(struct gcdbgfilter *filter, unsigned int zone,
+				struct gcmmucontext *gcmmucontext,
+				unsigned int surfwidth, unsigned int surfheight,
+				unsigned int surfbpp,
+				unsigned int x1, unsigned int y1,
+				unsigned int x2, unsigned int y2,
+				unsigned int gpuaddr)
+{
+	struct itembuffer itembuffer;
+	struct threadinfo *threadinfo;
+	unsigned int datasize;
+
+#if !GC_BUFFERED_OUTPUT
+	void *data;
+#endif
+
+	if (!g_outputbuffer.enable)
+		return;
+
+	if (GC_VERIFY_ENABLE(filter, zone)) {
+		mutex_lock(&g_lockmutex);
+
+		/* Locate thead entry. */
+		threadinfo = get_threadinfo(&g_outputbuffer);
+
+		/* Compute data size. */
+		datasize = (x2 - x1) * (y2 - y1) * surfbpp;
+
+		/* Fill in the sructure. */
+		itembuffer.itemtype = GC_BUFITEM_BUFFER;
+		itembuffer.buffertype = GC_BUFTYPE_SURFACE;
+		itembuffer.indent = threadinfo->msgindent
+				  + threadinfo->threadindent;
+		itembuffer.surfwidth = surfwidth;
+		itembuffer.surfheight = surfheight;
+		itembuffer.surfbpp = surfbpp;
+		itembuffer.x1 = x1;
+		itembuffer.y1 = y1;
+		itembuffer.x2 = x2;
+		itembuffer.y2 = y2;
+		itembuffer.datasize = datasize;
+		itembuffer.gpuaddr = gpuaddr;
+
+		/* Print the message. */
+#if GC_BUFFERED_OUTPUT
+		gc_append_buffer(gcmmucontext, &g_outputbuffer,
+					&itembuffer, NULL);
+#else
+		data = kmalloc(datasize, GFP_KERNEL);
+		if (data != NULL) {
+			gc_copy_surface(gcmmucontext, data, &itembuffer);
+			gc_print_buffer(NULL, &itembuffer,
+							(unsigned char *) data);
+			kfree(data);
+		}
+#endif
+
+		mutex_unlock(&g_lockmutex);
+	}
+}
+EXPORT_SYMBOL(gc_dump_phys_surface);
+
+
+/*******************************************************************************
+ * MMU dumping functions.
+ */
+
+struct gcmmuentry {
+	unsigned int entry;
+	bool exception;
+	bool present;
+
+	union {
+		struct gcmmumaster {
+			unsigned int slaveaddr;
+			unsigned int pagesize;
+		} mtlb;
+
+		struct gcmmuslave {
+			unsigned int pageaddr;
+			bool writable;
+		} stlb;
+	} u;
+};
+
+typedef void (*pfn_get_entry) (unsigned int entry,
+			       struct gcmmuentry *gcmmuentry);
+typedef void (*pfn_print_entry) (struct gcdbgfilter *filter,
+				 unsigned int zone,
+				 unsigned int index,
+				 struct gcmmuentry *gcmmuentry);
+
+struct gcmmutable {
+	char *name;
+	bool master;
+	unsigned int entry_count;
+	unsigned int vacant_entry;
+	pfn_get_entry get_entry;
+	pfn_print_entry print_entry;
+};
+
+static void get_mtlb_entry(unsigned int entry,
+			   struct gcmmuentry *gcmmuentry)
+{
+	static const unsigned int pagesize[] = {
+		1024 * 4,
+		1024 * 64,
+		1024 * 1024,
+		1024 * 1024 * 16
+	};
+
+	gcmmuentry->entry = entry;
+	gcmmuentry->exception = ((entry & GCMMU_MTLB_EXCEPTION_MASK) != 0);
+	gcmmuentry->present = ((entry & GCMMU_MTLB_PRESENT_MASK) != 0);
+	gcmmuentry->u.mtlb.slaveaddr = entry & GCMMU_MTLB_SLAVE_MASK;
+	gcmmuentry->u.mtlb.pagesize =
+		pagesize[(entry & GCMMU_MTLB_PAGE_SIZE_MASK) >> 2];
+}
+
+static void get_stlb_entry(unsigned int entry,
+			   struct gcmmuentry *gcmmuentry)
+{
+	gcmmuentry->entry = entry;
+	gcmmuentry->exception = ((entry & GCMMU_STLB_EXCEPTION_MASK) != 0);
+	gcmmuentry->present = ((entry & GCMMU_STLB_PRESENT_MASK) != 0);
+	gcmmuentry->u.stlb.pageaddr = entry & GCMMU_STLB_ADDRESS_MASK;
+	gcmmuentry->u.stlb.writable =
+		((entry & GCMMU_STLB_WRITEABLE_MASK) != 0);
+}
+
+static void print_mtlb_entry(struct gcdbgfilter *filter,
+			     unsigned int zone,
+			     unsigned int index,
+			     struct gcmmuentry *gcmmuentry)
+{
+	gc_dump_string(filter, zone,
+		       "  entry[%04d]: 0x%08X "
+		       "(stlbaddr=0x%08X, pagesize=%d, "
+		       "exception=%d, present=%d)\n",
+		       index, gcmmuentry->entry,
+		       gcmmuentry->u.mtlb.slaveaddr,
+		       gcmmuentry->u.mtlb.pagesize,
+		       gcmmuentry->exception,
+		       gcmmuentry->present);
+}
+
+static void print_stlb_entry(struct gcdbgfilter *filter,
+			     unsigned int zone,
+			     unsigned int index,
+			     struct gcmmuentry *gcmmuentry)
+{
+	gc_dump_string(filter, zone,
+		       "  entry[%04d]: 0x%08X "
+		       "(pageaddr=0x%08X, writable=%d, "
+		       "exception=%d, present=%d)\n",
+		       index, gcmmuentry->entry,
+		       gcmmuentry->u.stlb.pageaddr,
+		       gcmmuentry->u.stlb.writable,
+		       gcmmuentry->exception,
+		       gcmmuentry->present);
+}
+
+static void finalize_vacant(struct gcdbgfilter *filter, unsigned int zone,
+			    int index, int *vacant, int skipped)
+{
+	if (*vacant == -1)
+		return;
+
+	skipped = index - *vacant;
+	*vacant = -1;
+	gc_dump_string(filter, zone, "%15cskipped %d vacant entries\n",
+		       ' ', skipped);
+}
+
+static void finalize_allocated(struct gcdbgfilter *filter, unsigned int zone,
+			       int index, int *allocated, int skipped,
+			       struct gcmmuentry *gcmmuentry,
+			       unsigned int pagesize)
+{
+	unsigned int start, end;
+	int i;
+
+	if (*allocated == -1)
+		return;
+
+	skipped = index - *allocated;
+	*allocated = -1;
+	start = gcmmuentry->u.stlb.pageaddr - skipped * pagesize;
+	end   = gcmmuentry->u.stlb.pageaddr + pagesize;
+
+	if (skipped > 5) {
+		gc_dump_string(filter, zone,
+			       "%15cskipped %d allocated entries\n",
+			       ' ', skipped);
+		gc_dump_string(filter, zone,
+			       "%17callocated address range 0x%08X - 0x%08X\n",
+			       ' ', start, end);
+		gc_dump_string(filter, zone,
+			       "%17ctotal pages = %d\n",
+			       ' ', skipped + 1);
+		gc_dump_string(filter, zone,
+			       "%17ctotal buffer size = %d\n",
+			       ' ', (skipped + 1) * pagesize);
+	} else {
+		gcmmuentry->u.stlb.pageaddr = start + pagesize;
+		gcmmuentry->entry = (start + pagesize)
+				  & GCMMU_STLB_ADDRESS_MASK;
+
+		if (gcmmuentry->u.stlb.writable)
+			gcmmuentry->entry |= GCMMU_STLB_WRITEABLE_MASK;
+
+		if (gcmmuentry->exception)
+			gcmmuentry->entry |= GCMMU_STLB_EXCEPTION_MASK;
+
+		if (gcmmuentry->present)
+			gcmmuentry->entry |= GCMMU_STLB_PRESENT_MASK;
+
+		for (i = 0; i < skipped; i += 1) {
+			print_stlb_entry(filter, zone, index - skipped + i,
+					 gcmmuentry);
+			gcmmuentry->u.stlb.pageaddr += pagesize;
+		}
+	}
+}
+
+static void dump_mmu_table(struct gcdbgfilter *filter, unsigned int zone,
+			   struct gcmmutable *desc, unsigned int physical,
+			   unsigned int *logical, unsigned int pagesize)
+{
+	int vacant, allocated, skipped = 0;
+	bool sequential;
+	unsigned int entry, i;
+	struct gcmmuentry prev;
+	struct gcmmuentry curr;
+
+	gc_dump_string(filter, zone, "%s table:\n", desc->name);
+	gc_dump_string(filter, zone, "  physical=0x%08X\n", physical);
+
+	vacant = -1;
+	allocated = -1;
+	curr.present = false;
+
+	for (i = 0; i < desc->entry_count; i += 1) {
+		entry = logical[i];
+		prev = curr;
+		desc->get_entry(entry, &curr);
+
+		if (!curr.present) {
+			finalize_allocated(filter, zone,
+					   i, &allocated, skipped,
+					   &prev, pagesize);
+
+			if (entry == desc->vacant_entry) {
+				if (vacant == -1)
+					vacant = i;
+			} else {
+				finalize_vacant(filter, zone,
+						i, &vacant, skipped);
+
+				gc_dump_string(filter, zone,
+						" entry[%03d]: "
+						"invalid entry (0x%08X)\n",
+						i, entry);
+			}
+
+			continue;
+		}
+
+		finalize_vacant(filter, zone, i, &vacant, skipped);
+
+		sequential
+			 = (!desc->master
+			&& (curr.present == prev.present)
+			&& (curr.exception == prev.exception)
+			&& (curr.u.stlb.writable == prev.u.stlb.writable)
+			&& (curr.u.stlb.pageaddr == prev.u.stlb.pageaddr
+						  + pagesize));
+
+		if (sequential) {
+			if (allocated == -1)
+				allocated = i;
+
+			continue;
+		}
+
+		finalize_allocated(filter, zone, i, &allocated, skipped,
+				   &prev, pagesize);
+
+		desc->print_entry(filter, zone, i, &curr);
+	}
+
+	finalize_vacant(filter, zone, i, &vacant, skipped);
+	finalize_allocated(filter, zone, i, &allocated, skipped,
+			   &prev, pagesize);
+}
+
+void gc_dump_mmu(struct gcdbgfilter *filter, unsigned int zone,
+			struct gcmmucontext *gcmmucontext)
+{
+	static struct gcmmutable mtlb_desc = {
+		"Master",
+		true,
+		GCMMU_MTLB_ENTRY_NUM,
+		GCMMU_MTLB_ENTRY_VACANT,
+		get_mtlb_entry,
+		print_mtlb_entry
+	};
+
+	static struct gcmmutable stlb_desc = {
+		"Slave",
+		false,
+		GCMMU_STLB_ENTRY_NUM,
+		GCMMU_STLB_ENTRY_VACANT,
+		get_stlb_entry,
+		print_stlb_entry
+	};
+
+	unsigned int i;
+	struct gcmmuentry master;
+
+	GCDUMPARENAS(zone, "vacant arenas", &gcmmucontext->vacant);
+	GCDUMPARENAS(zone, "allocated arenas", &gcmmucontext->allocated);
+
+	gc_dump_string(filter, zone,
+		       "*** MMU DUMP ***\n");
+
+	dump_mmu_table(filter, zone, &mtlb_desc,
+		       gcmmucontext->master.physical,
+		       gcmmucontext->master.logical, 0);
+
+	for (i = 0; i < GCMMU_MTLB_ENTRY_NUM; i += 1) {
+		if (gcmmucontext->slave[i].logical == NULL)
+			continue;
+
+		get_mtlb_entry(gcmmucontext->master.logical[i], &master);
+		dump_mmu_table(filter, zone, &stlb_desc,
+				gcmmucontext->slave[i].physical,
+				gcmmucontext->slave[i].logical,
+				master.u.mtlb.pagesize);
+	}
+}
+EXPORT_SYMBOL(gc_dump_mmu);
+
+
+/*******************************************************************************
+ * Dumping control functions.
+ */
+
+void gc_dump_enable(void)
+{
+	mutex_lock(&g_lockmutex);
+
+	g_outputbuffer.enable = 1;
+	GC_PRINTK(NULL, "gcx dumping is enabled.\n");
+
+	mutex_unlock(&g_lockmutex);
+}
+EXPORT_SYMBOL(gc_dump_enable);
+
+void gc_dump_disable(void)
+{
+	mutex_lock(&g_lockmutex);
+
+	g_outputbuffer.enable = 0;
+	GC_PRINTK(NULL, "gcx dumping is disabled.\n");
+
+	mutex_unlock(&g_lockmutex);
+}
+EXPORT_SYMBOL(gc_dump_disable);
+
+void gc_dump_show_enabled(struct seq_file *s)
+{
+	struct list_head *filterhead;
+	struct gcdbgfilter *filter;
+	unsigned int i, zone;
+
+	mutex_lock(&g_lockmutex);
+
+	GC_PRINTK(s, "gcx logging is %s\n", g_outputbuffer.enable
+			? "enabled" : "disabled");
+
+	list_for_each(filterhead, &gc_filterlist) {
+		filter = list_entry(filterhead, struct gcdbgfilter,
+					link);
+
+		GC_PRINTK(s, "gcx filter '%s':\n", filter->filtername);
+		GC_PRINTK(s, "    zone mask = 0x%08X%s\n", filter->zone,
+				(filter->zone == 0)
+					? " (all disabled)" : "");
+
+		for (i = 0; filter->zonename[i] != NULL; i++) {
+			zone = 1 << i;
+			GC_PRINTK(s, "    0x%08X: %10s%s\n",
+					zone, filter->zonename[i],
+					((filter->zone & zone) != 0)
+						? " (enabled)" : "");
+		}
+	}
+
+	mutex_unlock(&g_lockmutex);
+}
+EXPORT_SYMBOL(gc_dump_show_enabled);
+
+void gc_dump_filter_enable(const char *filtername, int zone)
+{
+	struct list_head *filterhead;
+	struct gcdbgfilter *filter;
+	bool filterfound = false;
+	bool havesetzones = false;
+
+	mutex_lock(&g_lockmutex);
+
+	GC_PRINTK(NULL, "modifying zone mask for filter %s:\n", filtername);
+
+	list_for_each(filterhead, &gc_filterlist) {
+		filter = list_entry(filterhead, struct gcdbgfilter,
+					link);
+
+		if (strcasecmp(filtername, filter->filtername) == 0) {
+			GC_PRINTK(NULL, "  0x%08X --> 0x%08X\n",
+				filter->zone, zone);
+			filter->zone = zone;
+			filterfound = true;
+		}
+
+		if (filter->zone != 0)
+			havesetzones = true;
+	}
+
+	mutex_unlock(&g_lockmutex);
+
+	if (!filterfound)
+		GC_PRINTK(NULL, "  couldn't find filter %s.\n", filtername);
+
+	if (havesetzones && !g_outputbuffer.enable)
+		gc_dump_enable();
+	else if (!havesetzones && g_outputbuffer.enable)
+		gc_dump_disable();
+}
+EXPORT_SYMBOL(gc_dump_filter_enable);
+
+void gc_dbg_add_client(struct gcdbgfilter *filter)
+{
+	list_add(&filter->link, &gc_filterlist);
+}
+EXPORT_SYMBOL(gc_dbg_add_client);
+
+void gc_dump_flush(struct seq_file *s)
+{
+#if GC_BUFFERED_OUTPUT
+	mutex_lock(&g_lockmutex);
+
+	/*
+	 * Not dumping through debugfs for now because we have
+	 * too much data and it'd require us to implement the
+	 * seq_file iterator interface.
+	 */
+	gc_buffer_flush(NULL, &g_outputbuffer);
+
+	mutex_unlock(&g_lockmutex);
+#endif
+}
+EXPORT_SYMBOL(gc_dump_flush);
+
+void gc_dump_reset(void)
+{
+#if GC_BUFFERED_OUTPUT
+	mutex_lock(&g_lockmutex);
+
+	g_outputbuffer.start = 0;
+	g_outputbuffer.index = 0;
+	g_outputbuffer.count = 0;
+
+	GC_PRINTK(NULL, "gcx logging buffer is reset.\n");
+
+	mutex_unlock(&g_lockmutex);
+#endif
+}
+EXPORT_SYMBOL(gc_dump_reset);
+
+
+/*******************************************************************************
+ * Command buffer parser.
+ */
+
+int gc_parse_command_buffer(unsigned int *buffer, unsigned int size,
+				struct gccommandinfo *info)
+{
+	int res;
+	unsigned int i, j, itemcount, index, oldsrc;
+	unsigned int command, count, addr;
+
+	memset(info, 0, sizeof(struct gccommandinfo));
+	info->command = ~0U;
+
+	oldsrc = 0;
+
+	itemcount = (size + 3) / 4;
+	for (i = 0; i < itemcount;) {
+		command = (buffer[i] >> 27) & 0x1F;
+
+		switch (command) {
+		case GCREG_COMMAND_OPCODE_LOAD_STATE:
+			count = (buffer[i] >> 16) & 0x3F;
+			addr = buffer[i] & 0xFFFF;
+			i += 1;
+
+			for (j = 0; j < count; j += 1) {
+				switch (addr) {
+				case gcregDestAddressRegAddrs:
+					info->dst.surf.address = buffer[i];
+					break;
+
+				case gcregDestStrideRegAddrs:
+					info->dst.surf.stride = buffer[i];
+					break;
+
+				case gcregDestRotationConfigRegAddrs:
+					info->dst.surf.width
+						= buffer[i] & 0xFFFF;
+					break;
+
+				case gcregDstRotationHeightRegAddrs:
+					info->dst.surf.height
+						= buffer[i] & 0xFFFF;
+					break;
+
+				case gcregDestConfigRegAddrs:
+					info->command
+						= (buffer[i] >> 12) & 0xF;
+
+					info->dst.surf.swizzle
+						= (buffer[i] >> 16) & 0x3;
+
+					info->dst.surf.format
+						= buffer[i] & 0x1F;
+
+					info->dst.surf.bpp = gc_get_bpp(
+						info->dst.surf.format);
+					break;
+
+				case gcregSrcAddressRegAddrs:
+					info->src[0].surf.address = buffer[i];
+					oldsrc = 1;
+					break;
+
+				case gcregSrcStrideRegAddrs:
+					info->src[0].surf.stride = buffer[i];
+					break;
+
+				case gcregSrcRotationConfigRegAddrs:
+					info->src[0].surf.width
+						= buffer[i] & 0xFFFF;
+					break;
+
+				case gcregSrcRotationHeightRegAddrs:
+					info->src[0].surf.height
+						= buffer[i] & 0xFFFF;
+					break;
+
+				case gcregSrcConfigRegAddrs:
+					info->src[0].surf.swizzle
+						= (buffer[i] >> 20) & 0x3;
+
+					info->src[0].surf.format
+						= (buffer[i] >> 24) & 0x1F;
+
+					info->src[0].surf.bpp = gc_get_bpp(
+						info->src[0].surf.format);
+					break;
+
+				case gcregSrcOriginRegAddrs:
+					info->src[0].rect.left
+						= buffer[i] & 0xFFFF;
+
+					info->src[0].rect.top
+						= (buffer[i] >> 16) & 0xFFFF;
+					break;
+
+				case gcregSrcSizeRegAddrs:
+					info->src[0].rect.right
+						= buffer[i] & 0xFFFF;
+
+					info->src[0].rect.bottom
+						= (buffer[i] >> 16) & 0xFFFF;
+					break;
+
+				case gcregBlock4SrcAddressRegAddrs:
+				case gcregBlock4SrcAddressRegAddrs + 1:
+				case gcregBlock4SrcAddressRegAddrs + 2:
+				case gcregBlock4SrcAddressRegAddrs + 3:
+					index = addr & 3;
+					info->src[index].surf.address
+						= buffer[i];
+					break;
+
+				case gcregBlock4SrcStrideRegAddrs:
+				case gcregBlock4SrcStrideRegAddrs + 1:
+				case gcregBlock4SrcStrideRegAddrs + 2:
+				case gcregBlock4SrcStrideRegAddrs + 3:
+					index = addr & 3;
+					info->src[index].surf.stride
+						= buffer[i];
+					break;
+
+				case gcregBlock4SrcRotationConfigRegAddrs:
+				case gcregBlock4SrcRotationConfigRegAddrs + 1:
+				case gcregBlock4SrcRotationConfigRegAddrs + 2:
+				case gcregBlock4SrcRotationConfigRegAddrs + 3:
+					index = addr & 3;
+					info->src[index].surf.width
+						= buffer[i] & 0xFFFF;
+					break;
+
+				case gcregBlock4SrcRotationHeightRegAddrs:
+				case gcregBlock4SrcRotationHeightRegAddrs + 1:
+				case gcregBlock4SrcRotationHeightRegAddrs + 2:
+				case gcregBlock4SrcRotationHeightRegAddrs + 3:
+					index = addr & 3;
+					info->src[0].surf.height
+						= buffer[i] & 0xFFFF;
+					break;
+
+				case gcregBlock4SrcConfigRegAddrs:
+				case gcregBlock4SrcConfigRegAddrs + 1:
+				case gcregBlock4SrcConfigRegAddrs + 2:
+				case gcregBlock4SrcConfigRegAddrs + 3:
+					index = addr & 3;
+					info->src[index].surf.swizzle
+						= (buffer[i] >> 20) & 0x3;
+
+					info->src[index].surf.format
+						= (buffer[i] >> 24) & 0x1F;
+
+					info->src[index].surf.bpp = gc_get_bpp(
+						info->src[index].surf.format);
+					break;
+
+				case gcregBlock4SrcOriginRegAddrs:
+				case gcregBlock4SrcOriginRegAddrs + 1:
+				case gcregBlock4SrcOriginRegAddrs + 2:
+				case gcregBlock4SrcOriginRegAddrs + 3:
+					index = addr & 3;
+					info->src[index].rect.left
+						= buffer[i] & 0xFFFF;
+
+					info->src[index].rect.top
+						= (buffer[i] >> 16) & 0xFFFF;
+					break;
+
+				case gcregBlock4SrcSizeRegAddrs:
+				case gcregBlock4SrcSizeRegAddrs + 1:
+				case gcregBlock4SrcSizeRegAddrs + 2:
+				case gcregBlock4SrcSizeRegAddrs + 3:
+					index = addr & 3;
+					info->src[index].rect.right
+						= buffer[i] & 0xFFFF;
+
+					info->src[index].rect.bottom
+						= (buffer[i] >> 16) & 0xFFFF;
+					break;
+
+				case gcregDEMultiSourceRegAddrs:
+					info->srccount = (buffer[i] & 0x7) + 1;
+					break;
+				}
+
+				addr += 1;
+				i += 1;
+			}
+
+			i += ((~count) & 1);
+			break;
+
+		case GCREG_COMMAND_OPCODE_END:
+		case GCREG_COMMAND_OPCODE_NOP:
+		case GCREG_COMMAND_OPCODE_WAIT:
+		case GCREG_COMMAND_OPCODE_LINK:
+		case GCREG_COMMAND_OPCODE_STALL:
+			i += 2;
+			break;
+
+		case GCREG_COMMAND_OPCODE_STARTDE:
+			info->dst.rectcount = (buffer[i] >> 8) & 0xFF;
+			i += 2;
+
+			for (j = 0; j < info->dst.rectcount; j += 1) {
+				info->dst.rect[j].left
+						= buffer[i] & 0xFFFF;
+				info->dst.rect[j].top
+						= (buffer[i] >> 16) & 0xFFFF;
+				i += 1;
+
+				info->dst.rect[j].right
+						= buffer[i] & 0xFFFF;
+				info->dst.rect[j].bottom
+						= (buffer[i] >> 16) & 0xFFFF;
+				i += 1;
+			}
+			break;
+
+		default:
+			res = 0;
+			gc_dump_string(NULL, 0,
+					"bad command (%d) "
+					"while parsing the command stream",
+					command);
+			goto exit;
+		}
+
+	}
+
+	/* Enable old source. */
+	if ((info->srccount == 0) && oldsrc)
+		info->srccount = 1;
+
+	/* Success. */
+	res = 1;
+
+exit:
+	return res;
+}
+EXPORT_SYMBOL(gc_parse_command_buffer);
+
+/*******************************************************************************
+ * Bltsville debugging.
+ */
+
+char *gc_bvblend_name(enum bvblend blend)
+{
+	switch (blend) {
+	case BVBLEND_CLEAR:		return "BVBLEND_CLEAR";
+	case BVBLEND_SRC1:		return "BVBLEND_SRC1";
+	case BVBLEND_SRC2:		return "BVBLEND_SRC2";
+	case BVBLEND_SRC1OVER:		return "BVBLEND_SRC1OVER";
+	case BVBLEND_SRC2OVER:		return "BVBLEND_SRC2OVER";
+	case BVBLEND_SRC1IN:		return "BVBLEND_SRC1IN";
+	case BVBLEND_SRC2IN:		return "BVBLEND_SRC2IN";
+	case BVBLEND_SRC1OUT:		return "BVBLEND_SRC1OUT";
+	case BVBLEND_SRC2OUT:		return "BVBLEND_SRC2OUT";
+	case BVBLEND_SRC1ATOP:		return "BVBLEND_SRC1ATOP";
+	case BVBLEND_SRC2ATOP:		return "BVBLEND_SRC2ATOP";
+	case BVBLEND_XOR:		return "BVBLEND_XOR";
+	case BVBLEND_PLUS:		return "BVBLEND_PLUS";
+	case BVBLEND_NORMAL:		return "BVBLEND_NORMAL";
+	case BVBLEND_LIGHTEN:		return "BVBLEND_LIGHTEN";
+	case BVBLEND_DARKEN:		return "BVBLEND_DARKEN";
+	case BVBLEND_MULTIPLY:		return "BVBLEND_MULTIPLY";
+	case BVBLEND_AVERAGE:		return "BVBLEND_AVERAGE";
+	case BVBLEND_ADD:		return "BVBLEND_ADD";
+	case BVBLEND_SUBTRACT:		return "BVBLEND_SUBTRACT";
+	case BVBLEND_DIFFERENCE:	return "BVBLEND_DIFFERENCE";
+	case BVBLEND_NEGATE:		return "BVBLEND_NEGATE";
+	case BVBLEND_SCREEN:		return "BVBLEND_SCREEN";
+	case BVBLEND_EXCLUSION:		return "BVBLEND_EXCLUSION";
+	case BVBLEND_OVERLAY:		return "BVBLEND_OVERLAY";
+	case BVBLEND_SOFT_LIGHT:	return "BVBLEND_SOFT_LIGHT";
+	case BVBLEND_HARD_LIGHT:	return "BVBLEND_HARD_LIGHT";
+	case BVBLEND_COLOR_DODGE:	return "BVBLEND_COLOR_DODGE";
+	case BVBLEND_COLOR_BURN:	return "BVBLEND_COLOR_BURN";
+	case BVBLEND_LINEAR_LIGHT:	return "BVBLEND_LINEAR_LIGHT";
+	case BVBLEND_VIVID_LIGHT:	return "BVBLEND_VIVID_LIGHT";
+	case BVBLEND_PIN_LIGHT:		return "BVBLEND_PIN_LIGHT";
+	case BVBLEND_HARD_MIX:		return "BVBLEND_HARD_MIX";
+	case BVBLEND_REFLECT:		return "BVBLEND_REFLECT";
+	case BVBLEND_GLOW:		return "BVBLEND_GLOW";
+	case BVBLEND_PHOENIX:		return "BVBLEND_PHOENIX";
+	default:			return "[UNKNOWN]";
+	}
+}
+EXPORT_SYMBOL(gc_bvblend_name);
+
+
+/*******************************************************************************
+ * Initialization/cleanup.
+ */
+
+void gcdbg_init(void)
+{
+#if GC_BUFFERED_OUTPUT
+	/* Allocate the debug buffer. */
+	g_outputbuffer.buffer = kmalloc(GC_DUMP_BUFFER_SIZE, GFP_KERNEL);
+	if (g_outputbuffer.buffer == NULL) {
+		GC_PRINTK(NULL, "failed to allocate dump buffer.\n");
+		return;
+	}
+#endif
+
+	g_initdone = true;
+}
+
+void gcdbg_exit(void)
+{
+#if GC_BUFFERED_OUTPUT
+	if (g_outputbuffer.buffer != NULL) {
+		kfree(g_outputbuffer.buffer);
+		g_outputbuffer.buffer = NULL;
+	}
+#endif
+
+	g_initdone = false;
+}
+
+#endif /* GCDEBUG_ENABLE */
diff --git a/drivers/misc/gcx/gccore/gcdebug.c b/drivers/misc/gcx/gccore/gcdebug.c
new file mode 100644
index 0000000..814bd38
--- /dev/null
+++ b/drivers/misc/gcx/gccore/gcdebug.c
@@ -0,0 +1,555 @@
+/*
+ * gcdebug.c
+ *
+ * Copyright (C) 2010-2011 Vivante Corporation.
+ *
+ * This package is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#include <linux/debugfs.h>
+#include <linux/seq_file.h>
+#include <linux/module.h>
+#include <linux/uaccess.h>
+#include <linux/delay.h>
+#include <linux/gcx.h>
+#include <linux/gccore.h>
+#include "gcmain.h"
+
+#define MMU_UNITS  4
+#define MMU_ERROR(irq_ack) ((irq_ack & 0x40000000) != 0)
+
+#if GCDEBUG_ENABLE
+#define STATUS_DUMP(s, msg, ...)					\
+	do {								\
+		if (s)							\
+			seq_printf(s, msg, __VA_ARGS__);		\
+		else							\
+			gc_dump_string(NULL, 0, msg, __VA_ARGS__);	\
+	} while (0)
+#else
+#define STATUS_DUMP(s, msg, ...)					\
+	do {								\
+		if (s)							\
+			seq_printf(s, msg, __VA_ARGS__);		\
+		else							\
+			printk(KERN_ERR msg, __VA_ARGS__);		\
+	} while (0)
+#endif
+
+enum gc_debug_when {
+	GC_DEBUG_USER_REQUEST,
+	GC_DEBUG_DRIVER_POWEROFF,
+	GC_DEBUG_DRIVER_IRQ,
+	GC_DEBUG_DRIVER_REQUEST,
+};
+
+struct gc_gpu_id {
+	bool	     valid;
+	unsigned int chipModel;
+	unsigned int chipRevision;
+	unsigned int chipDate;
+	unsigned int chipTime;
+	unsigned int chipFeatures;
+	unsigned int chipMinorFeatures;
+};
+
+static struct gc_gpu_id g_gcGpuId;
+static struct dentry *debug_root;
+
+void gc_debug_cache_gpu_id(void)
+{
+	if (g_gcGpuId.valid) {
+		/* only cached once */
+		return;
+	}
+
+	g_gcGpuId.chipModel = gc_read_reg(GC_CHIP_ID_Address);
+	g_gcGpuId.chipRevision = gc_read_reg(GC_CHIP_REV_Address);
+	g_gcGpuId.chipDate = gc_read_reg(GC_CHIP_DATE_Address);
+	g_gcGpuId.chipTime = gc_read_reg(GC_CHIP_TIME_Address);
+	g_gcGpuId.chipFeatures = gc_read_reg(GC_FEATURES_Address);
+	g_gcGpuId.chipMinorFeatures = gc_read_reg(GC_FEATURES0_Address);
+	g_gcGpuId.valid = 1;
+}
+
+static int gc_debug_show_gpu_id(struct seq_file *s, void *unused)
+{
+	if (!g_gcGpuId.valid) {
+		seq_printf(s, "GC gpu id cache not valid.  "
+			   "GC must be powered on once.\n");
+		return 0;
+	}
+
+	seq_printf(s, "model=%X\n", g_gcGpuId.chipModel);
+	seq_printf(s, "revision=%X\n", g_gcGpuId.chipRevision);
+	seq_printf(s, "date=%X\n", g_gcGpuId.chipDate);
+	seq_printf(s, "time=%X\n", g_gcGpuId.chipTime);
+	seq_printf(s, "chipFeatures=0x%08X\n", g_gcGpuId.chipFeatures);
+
+	return 0;
+}
+
+static int gc_debug_open_gpu_id(struct inode *inode, struct file *file)
+{
+	return single_open(file, gc_debug_show_gpu_id, inode->i_private);
+}
+
+static const struct file_operations gc_debug_fops_gpu_id = {
+	.open = gc_debug_open_gpu_id,
+	.read = seq_read,
+	.llseek = seq_lseek,
+	.release = single_release,
+};
+
+struct gc_gpu_status {
+	bool		   valid;
+	bool           dma_addr_changing;
+	const char        *name;
+	unsigned int	   idle;
+	unsigned int	   dma_state;
+	unsigned int	   dma_addr;
+	unsigned int	   dma_low_data;
+	unsigned int	   dma_high_data;
+	unsigned int	   total_reads;
+	unsigned int	   total_writes;
+	unsigned int	   total_read_bursts;
+	unsigned int	   total_write_bursts;
+	unsigned int	   total_read_reqs;
+	unsigned int	   total_write_reqs;
+	unsigned int	   irq_acknowledge;
+	unsigned int	   mmu_status;
+	unsigned int	   exception_address[MMU_UNITS];
+};
+
+enum gc_debug_when gc_gpu_status_when;
+
+struct gc_gpu_status gc_gpu_status = {
+	.name = "GPU status"
+};
+struct gc_gpu_status gc_gpu_status_last_error = {
+	.name = "GPU last error status"
+};
+
+/* By default we don't cache the status on every irq */
+static int gc_cache_status_every_irq;
+
+
+static bool gc_dma_addr_changing(void)
+{
+	static const unsigned int detectcount = 1000;
+	unsigned int address1, address2;
+	unsigned int i;
+
+	address1 = gc_read_reg(GCREG_FE_DEBUG_CUR_CMD_ADR_Address);
+	for (i = 0; i < detectcount; i += 1) {
+		address2 = gc_read_reg(GCREG_FE_DEBUG_CUR_CMD_ADR_Address);
+		if (address1 != address2)
+			break;
+	}
+
+	return i < detectcount;
+}
+
+void gc_debug_cache_gpu_status(
+	struct gc_gpu_status *status,
+	unsigned int acknowledge)
+{
+	int i;
+
+	if (!status) {
+		status = &gc_gpu_status;
+		gc_gpu_status_when = GC_DEBUG_DRIVER_REQUEST;
+	}
+
+	status->dma_addr_changing = gc_dma_addr_changing();
+
+	status->idle =
+		gc_read_reg(GCREG_HI_IDLE_Address);
+	status->dma_state =
+		gc_read_reg(GCREG_FE_DEBUG_STATE_Address);
+	status->dma_addr =
+		gc_read_reg(GCREG_FE_DEBUG_CUR_CMD_ADR_Address);
+	status->dma_low_data =
+		gc_read_reg(GCREG_FE_DEBUG_CMD_LOW_REG_Address);
+	status->dma_high_data =
+		gc_read_reg(GCREG_FE_DEBUG_CMD_HI_REG_Address);
+	status->total_reads =
+		gc_read_reg(GC_TOTAL_READS_Address);
+	status->total_writes =
+		gc_read_reg(GC_TOTAL_WRITES_Address);
+	status->total_read_bursts =
+		gc_read_reg(GC_TOTAL_READ_BURSTS_Address);
+	status->total_write_bursts =
+		gc_read_reg(GC_TOTAL_WRITE_BURSTS_Address);
+	status->total_read_reqs =
+		gc_read_reg(GC_TOTAL_READ_REQS_Address);
+	status->total_write_reqs =
+		gc_read_reg(GC_TOTAL_WRITE_REQS_Address);
+	status->irq_acknowledge = acknowledge;
+
+	/* Is it valid/useful to read the mmu registers for
+	 * other error conditions? */
+	if (MMU_ERROR(acknowledge)) {
+		status->mmu_status =
+			gc_read_reg(GCREG_MMU_STATUS_Address);
+
+		for (i = 0; i < MMU_UNITS; i++)
+			status->exception_address[i] =
+				gc_read_reg(GCREG_MMU_EXCEPTION_Address + i);
+	} else {
+		status->mmu_status = 0;
+
+		for (i = 0; i < MMU_UNITS; i++)
+			status->exception_address[i] = 0;
+	}
+
+	status->valid = true;
+}
+
+void gc_debug_cache_gpu_status_from_irq(unsigned int acknowledge)
+{
+	bool haveError = (acknowledge & 0xC0000000) != 0;
+
+	if (!gc_cache_status_every_irq && !haveError) {
+		/* called from irq, no error, not caching every irq */
+		return;
+	}
+
+	gc_debug_cache_gpu_status(&gc_gpu_status, acknowledge);
+	gc_gpu_status_when = GC_DEBUG_DRIVER_IRQ;
+
+	if (haveError)
+		memcpy(&gc_gpu_status_last_error, &gc_gpu_status,
+		       sizeof(struct gc_gpu_status));
+}
+
+static const char *gc_power_string(enum gcpower power)
+{
+	switch (power) {
+	case GCPWR_UNKNOWN:
+		return "GCPWR_UNKNOWN";
+	case GCPWR_OFF:
+		return "GCPWR_OFF";
+	case GCPWR_ON:
+		return "GCPWR_ON";
+	case GCPWR_LOW:
+		return "GCPWR_LOW";
+	}
+
+	return "unknown";
+}
+
+static const char *gc_when_string(enum gc_debug_when when)
+{
+	switch (when) {
+	case GC_DEBUG_USER_REQUEST:
+		return "GC_DEBUG_USER_REQUEST";
+	case GC_DEBUG_DRIVER_POWEROFF:
+		return "GC_DEBUG_DRIVER_POWEROFF";
+	case GC_DEBUG_DRIVER_REQUEST:
+		return "GC_DEBUG_DRIVER_REQUEST";
+	case GC_DEBUG_DRIVER_IRQ:
+		return "GC_DEBUG_DRIVER_IRQ";
+	}
+
+	return "unknown";
+}
+
+
+static void gc_dump_status_internal(struct seq_file *s,
+				    struct gc_gpu_status *status)
+{
+	if (!status->valid) {
+		STATUS_DUMP(s, "%s: not valid.\n", status->name);
+		return;
+	}
+
+	STATUS_DUMP(s, "  idle = 0x%08X\n", status->idle);
+	STATUS_DUMP(s, "  DMA state = 0x%08X\n", status->dma_state);
+	STATUS_DUMP(s, "  DMA address = 0x%08X (%s)\n", status->dma_addr,
+		    status->dma_addr_changing ? "running" : "not running");
+	STATUS_DUMP(s, "  DMA low data = 0x%08X\n", status->dma_low_data);
+	STATUS_DUMP(s, "  DMA high data = 0x%08X\n", status->dma_high_data);
+	STATUS_DUMP(s, "  Total memory reads = %d\n", status->total_reads);
+	STATUS_DUMP(s, "  Total memory writes = %d\n", status->total_writes);
+	STATUS_DUMP(s, "  Total memory read 64-bit bursts = %d\n",
+				status->total_read_bursts);
+	STATUS_DUMP(s, "  Total memory write 64-bit bursts = %d\n",
+				status->total_write_bursts);
+	STATUS_DUMP(s, "  Total memory read requests = %d\n",
+				status->total_read_reqs);
+	STATUS_DUMP(s, "  Total memory write requests = %d\n",
+				status->total_write_reqs);
+
+	if (MMU_ERROR(status->irq_acknowledge)) {
+		int i;
+
+		STATUS_DUMP(s, "mmu status = 0x%08X\n", status->mmu_status);
+
+		for (i = 0; i < MMU_UNITS; i++)
+			STATUS_DUMP(s, "exception address %d = 0x%08X\n",
+				    i, status->exception_address[i]);
+	}
+}
+
+void gc_debug_dump_status(const char *function, int line)
+{
+	STATUS_DUMP(NULL, "Current GC gpu status requested from %s(%d).\n",
+				function, line);
+
+	gc_debug_cache_gpu_status(&gc_gpu_status, 0);
+	gc_gpu_status_when = GC_DEBUG_DRIVER_REQUEST;
+
+	gc_dump_status_internal(NULL, &gc_gpu_status);
+
+	GCDBG_FLUSHDUMP(NULL);
+}
+
+static int gc_debug_show_gpu_status(struct seq_file *s, void *data)
+{
+	const char *powerString = gc_power_string(gcpwr_get());
+
+	struct gc_gpu_status *status = (struct gc_gpu_status *)s->private;
+
+	if (!status) {
+		printk(KERN_ERR "%s: null status\n", __func__);
+		return 0;
+	}
+
+	seq_printf(s, "GC gpu current power status: %s\n", powerString);
+
+	if (gcpwr_get() == GCPWR_ON) {
+		/* update the gpu status now */
+		gc_debug_cache_gpu_status(&gc_gpu_status, 0);
+		gc_gpu_status_when = GC_DEBUG_USER_REQUEST;
+	}
+
+	seq_printf(s, "%s: cached at: %s\n", status->name,
+			   gc_when_string(gc_gpu_status_when));
+
+	gc_dump_status_internal(s, status);
+
+	return 0;
+}
+
+static int gc_debug_open_gpu_status(struct inode *inode, struct file *file)
+{
+	return single_open(file, gc_debug_show_gpu_status, &gc_gpu_status);
+}
+
+static const struct file_operations gc_debug_fops_gpu_status = {
+	.open = gc_debug_open_gpu_status,
+	.read = seq_read,
+	.llseek = seq_lseek,
+	.release = single_release,
+};
+
+static int gc_debug_open_gpu_last_error(struct inode *inode, struct file *file)
+{
+	return single_open(file,
+			   gc_debug_show_gpu_status,
+			   &gc_gpu_status_last_error);
+}
+
+static const struct file_operations gc_debug_fops_gpu_last_error = {
+	.open = gc_debug_open_gpu_last_error,
+	.read = seq_read,
+	.llseek = seq_lseek,
+	.release = single_release,
+};
+
+/*****************************************************************************/
+
+static int gc_debug_show_log_dump(struct seq_file *s, void *data)
+{
+	GCDBG_FLUSHDUMP(s);
+	return 0;
+}
+
+static int gc_debug_open_log_dump(struct inode *inode, struct file *file)
+{
+	return single_open(file, gc_debug_show_log_dump, 0);
+}
+
+static const struct file_operations gc_debug_fops_log_dump = {
+	.open = gc_debug_open_log_dump,
+	.read = seq_read,
+	.llseek = seq_lseek,
+	.release = single_release,
+};
+
+/*****************************************************************************/
+
+static int gc_debug_show_log_enable(struct seq_file *s, void *data)
+{
+	GCDBG_SHOWENABLED(s);
+	return 0;
+}
+
+static int gc_debug_open_log_enable(struct inode *inode, struct file *file)
+{
+	return single_open(file, gc_debug_show_log_enable, 0);
+}
+
+static ssize_t gc_debug_write_log_enable(
+	struct file *file,
+	const char __user *user_buf,
+	size_t count, loff_t *ppos)
+{
+	char buf[256];
+	size_t len;
+	unsigned long val;
+	int ret;
+	char *name = 0;
+
+	len = min(count, sizeof(buf) - 1);
+	if (copy_from_user(buf, user_buf, len))
+		return -EFAULT;
+
+	buf[len] = '\0';
+
+	ret = kstrtoul(buf, 0, &val);
+	if (ret < 0) {
+		int i;
+		for (i = 0; i < len - 1; i++) {
+			if (buf[i] == ' ') {
+				buf[i] = 0;
+
+				ret = kstrtoul(&buf[i+1], 0, &val);
+				if (ret < 0)
+					return -EINVAL;
+
+				name = &buf[0];
+				break;
+			}
+		}
+
+		if (!name)
+			return -EINVAL;
+	}
+
+	if (name)
+		GCDBG_SETFILTER(name, val);
+	else if (val)
+		GCDBG_ENABLEDUMP();
+	else
+		GCDBG_DISABLEDUMP();
+
+	return count;
+}
+
+static const struct file_operations gc_debug_fops_log_enable = {
+	.open    = gc_debug_open_log_enable,
+	.write   = gc_debug_write_log_enable,
+	.read    = seq_read,
+	.llseek  = seq_lseek,
+	.release = single_release,
+};
+
+/*****************************************************************************/
+
+static int gc_debug_show_log_reset(struct seq_file *s, void *data)
+{
+	GCDBG_RESETDUMP();
+	return 0;
+}
+
+static int gc_debug_open_log_reset(struct inode *inode, struct file *file)
+{
+	return single_open(file, gc_debug_show_log_reset, 0);
+}
+
+static ssize_t gc_debug_write_log_reset(
+	struct file *file,
+	const char __user *user_buf,
+	size_t count, loff_t *ppos)
+{
+	GCDBG_RESETDUMP();
+	return count;
+}
+
+static const struct file_operations gc_debug_fops_log_reset = {
+	.open    = gc_debug_open_log_reset,
+	.write   = gc_debug_write_log_reset,
+	.read    = seq_read,
+	.llseek  = seq_lseek,
+	.release = single_release,
+};
+
+/*****************************************************************************/
+
+static int gc_debug_show_cur_freq(struct seq_file *s, void *data)
+{
+	unsigned mhz = gcpwr_get_speed();
+	if (mhz)
+		seq_printf(s, "cur freq: %d mhz\n", mhz);
+	else
+		seq_printf(s, "unable to read cur freq\n");
+
+	return 0;
+}
+
+static int gc_debug_open_cur_freq(struct inode *inode, struct file *file)
+{
+	return single_open(file, gc_debug_show_cur_freq, 0);
+}
+
+static const struct file_operations gc_debug_fops_cur_freq = {
+	.open    = gc_debug_open_cur_freq,
+	.write   = NULL,
+	.read    = seq_read,
+	.llseek  = seq_lseek,
+	.release = single_release,
+};
+
+/*****************************************************************************/
+
+void gc_debug_init(void)
+{
+	struct dentry *logDir;
+
+	debug_root = debugfs_create_dir("gcx", NULL);
+	if (!debug_root)
+		return;
+
+	debugfs_create_file("id", 0664, debug_root, NULL,
+			    &gc_debug_fops_gpu_id);
+	debugfs_create_file("status", 0664, debug_root, NULL,
+			    &gc_debug_fops_gpu_status);
+	debugfs_create_file("last_error", 0664, debug_root, NULL,
+			    &gc_debug_fops_gpu_last_error);
+	debugfs_create_bool("cache_status_every_irq", 0664, debug_root,
+			    &gc_cache_status_every_irq);
+	debugfs_create_file("cur_freq", 0664, debug_root, NULL,
+			    &gc_debug_fops_cur_freq);
+
+	logDir = debugfs_create_dir("log", debug_root);
+	if (!logDir)
+		return;
+
+	debugfs_create_file("enable", 0664, logDir, NULL,
+						&gc_debug_fops_log_enable);
+	debugfs_create_file("reset", 0664, logDir, NULL,
+						&gc_debug_fops_log_reset);
+	debugfs_create_file("dump", 0664, logDir, NULL,
+						&gc_debug_fops_log_dump);
+}
+
+void gc_debug_shutdown(void)
+{
+	if (debug_root)
+		debugfs_remove_recursive(debug_root);
+}
+
+/* called just BEFORE powering off */
+void gc_debug_poweroff_cache(void)
+{
+	/* gpu id is read only once */
+	gc_debug_cache_gpu_id();
+}
diff --git a/drivers/misc/gcx/gccore/gcmain.c b/drivers/misc/gcx/gccore/gcmain.c
new file mode 100644
index 0000000..0e9d4b8
--- /dev/null
+++ b/drivers/misc/gcx/gccore/gcmain.c
@@ -0,0 +1,1101 @@
+/*
+ * gcmain.c
+ *
+ * Copyright (C) 2010-2011 Vivante Corporation.
+ *
+ * This package is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/uaccess.h>
+#include <linux/pm_runtime.h>
+#include <linux/delay.h>
+#include <plat/omap_gcx.h>
+#include <linux/opp.h>
+#include <linux/io.h>
+#include <plat/omap_hwmod.h>
+#include <plat/omap-pm.h>
+#include "gcmain.h"
+
+#define GCZONE_NONE		0
+#define GCZONE_ALL		(~0U)
+#define GCZONE_INIT		(1 << 0)
+#define GCZONE_CONTEXT		(1 << 1)
+#define GCZONE_POWER		(1 << 2)
+#define GCZONE_COMMIT		(1 << 3)
+#define GCZONE_MAPPING		(1 << 4)
+#define GCZONE_PROBE		(1 << 5)
+#define GCZONE_CALLBACK		(1 << 6)
+#define GCZONE_FREQSCALE	(1 << 7)
+
+GCDBG_FILTERDEF(core, GCZONE_NONE,
+		"init",
+		"context",
+		"power",
+		"commit",
+		"mapping",
+		"probe",
+		"callback",
+		"freqscale")
+
+
+#if !defined(GC_ENABLE_SUSPEND)
+#define GC_ENABLE_SUSPEND 1
+#endif
+
+#if !defined(CONFIG_HAS_EARLYSUSPEND)
+#define CONFIG_HAS_EARLYSUSPEND 0
+#endif
+
+/* Driver private data. */
+static struct gccorecontext g_context;
+
+
+/*******************************************************************************
+ * Context management.
+ */
+
+static enum gcerror find_context(struct gccorecontext *gccorecontext,
+				 bool fromuser,
+				 struct gcmmucontext **gcmmucontext)
+{
+	enum gcerror gcerror = GCERR_NONE;
+	struct list_head *ctxhead;
+	struct gcmmucontext *temp = NULL;
+	pid_t pid;
+
+	GCENTER(GCZONE_CONTEXT);
+
+	/* Get current PID. */
+	pid = fromuser ? current->tgid : 0;
+
+	/* Search the list. */
+	GCDBG(GCZONE_CONTEXT, "scanning context records for pid %d.\n", pid);
+
+	/* Try to locate the record. */
+	list_for_each(ctxhead, &gccorecontext->mmuctxlist) {
+		temp = list_entry(ctxhead, struct gcmmucontext, link);
+		if (temp->pid == pid) {
+			/* Success. */
+			GCDBG(GCZONE_CONTEXT, "context is found @ 0x%08X\n",
+				(unsigned int) temp);
+
+			goto exit;
+		}
+	}
+
+	/* Get new record. */
+	if (list_empty(&gccorecontext->mmuctxvac)) {
+		GCDBG(GCZONE_CONTEXT, "not found, allocating.\n");
+
+		temp = kmalloc(sizeof(struct gcmmucontext), GFP_KERNEL);
+		if (temp == NULL) {
+			GCERR("out of memory.\n");
+			gcerror = GCERR_SETGRP(GCERR_OODM,
+						GCERR_IOCTL_CTX_ALLOC);
+			goto fail;
+		}
+
+		GCDBG(GCZONE_CONTEXT, "allocated @ 0x%08X\n",
+			(unsigned int) temp);
+	} else {
+		ctxhead = gccorecontext->mmuctxvac.next;
+		temp = list_entry(ctxhead, struct gcmmucontext, link);
+		list_del(ctxhead);
+
+		GCDBG(GCZONE_CONTEXT, "not found, reusing vacant @ 0x%08X\n",
+			(unsigned int) temp);
+	}
+
+	gcerror = gcmmu_create_context(gccorecontext, temp, pid);
+	if (gcerror != GCERR_NONE)
+		goto fail;
+
+	/* Add the context to the list. */
+	list_add(&temp->link, &gccorecontext->mmuctxlist);
+
+exit:
+	*gcmmucontext = temp;
+
+	GCEXIT(GCZONE_CONTEXT);
+	return GCERR_NONE;
+
+fail:
+	if (temp != NULL) {
+		gcmmu_destroy_context(gccorecontext, temp);
+		list_add(&temp->link, &gccorecontext->mmuctxvac);
+	}
+
+	GCEXITARG(GCZONE_CONTEXT, "gcerror = 0x%08X\n", gcerror);
+	return gcerror;
+}
+
+static void destroy_mmu_context(struct gccorecontext *gccorecontext)
+{
+	struct list_head *head;
+	struct gcmmucontext *temp;
+
+	/* Free vacant entry list. */
+	while (!list_empty(&gccorecontext->mmuctxvac)) {
+		head = gccorecontext->mmuctxvac.next;
+		temp = list_entry(head, struct gcmmucontext, link);
+		list_del(head);
+		kfree(temp);
+	}
+
+	/* Free active contexts. */
+	while (!list_empty(&gccorecontext->mmuctxlist)) {
+		head = gccorecontext->mmuctxlist.next;
+		temp = list_entry(head, struct gcmmucontext, link);
+		gcmmu_destroy_context(gccorecontext, temp);
+		list_del(head);
+		kfree(temp);
+	}
+}
+
+struct device *gc_get_dev(void)
+{
+	return g_context.device;
+}
+EXPORT_SYMBOL(gc_get_dev);
+
+
+/*******************************************************************************
+** Register access.
+*/
+
+unsigned int gc_read_reg(unsigned int address)
+{
+	return readl((unsigned char *) g_context.regbase + address);
+}
+
+void gc_write_reg(unsigned int address, unsigned int data)
+{
+	writel(data, (unsigned char *) g_context.regbase + address);
+}
+
+
+/*******************************************************************************
+ * Power management.
+ */
+
+static void gcpwr_enable_clock(struct gccorecontext *gccorecontext)
+{
+	bool ctxlost;
+
+	GCENTER(GCZONE_POWER);
+
+	ctxlost = gccorecontext->plat->get_context_loss_count(gccorecontext->device);
+
+	if (!gccorecontext->clockenabled) {
+		/* Enable the clock. */
+		pm_runtime_get_sync(gccorecontext->device);
+
+		/* Signal software not idle. */
+		gc_write_reg(GC_GP_OUT0_Address, 0);
+
+		/* Clock enabled. */
+		gccorecontext->clockenabled = true;
+	} else if (ctxlost) {
+		GCDBG(GCZONE_POWER, "hardware context lost.\n");
+		if (gc_read_reg(GC_GP_OUT0_Address)) {
+			GCDBG(GCZONE_POWER, "reset idle register.\n");
+			gc_write_reg(GC_GP_OUT0_Address, 0);
+		}
+	}
+
+	GCDBG(GCZONE_POWER, "clock %s.\n",
+		gccorecontext->clockenabled ? "enabled" : "disabled");
+
+	if (ctxlost || (gccorecontext->gcpower == GCPWR_UNKNOWN))
+		gcpwr_reset(gccorecontext);
+
+	GCEXIT(GCZONE_POWER);
+}
+
+static void gcpwr_disable_clock(struct gccorecontext *gccorecontext)
+{
+	GCENTER(GCZONE_POWER);
+
+	if (gccorecontext->clockenabled) {
+		gc_debug_poweroff_cache();
+
+		/* Signal software idle. */
+		gc_write_reg(GC_GP_OUT0_Address, 1);
+
+		/* Disable the clock. */
+		pm_runtime_put_sync(gccorecontext->device);
+
+		/* Clock disabled. */
+		gccorecontext->clockenabled = false;
+	}
+
+	GCDBG(GCZONE_POWER, "clock %s.\n",
+		gccorecontext->clockenabled ? "enabled" : "disabled");
+
+	GCEXIT(GCZONE_POWER);
+}
+
+static void gcpwr_scale(struct gccorecontext *gccorecontext, int index)
+{
+	int ret;
+
+	GCENTERARG(GCZONE_FREQSCALE, "index=%d\n", index);
+
+	if ((index < 0) || (index >= gccorecontext->opp_count)) {
+		GCERR("invalid index %d.\n", index);
+		goto exit;
+	}
+
+	if ((gccorecontext->plat == NULL) ||
+	    (gccorecontext->plat->scale_dev == NULL)) {
+		GCERR("scale interface is not initialized.\n");
+		goto exit;
+	}
+
+	if (gccorecontext->cur_freq == gccorecontext->opp_freqs[index])
+		goto exit;
+
+	ret = gccorecontext->plat->scale_dev(gccorecontext->bb2ddevice,
+					     gccorecontext->opp_freqs[index]);
+	if (ret != 0) {
+		GCERR("failed to scale the device.\n");
+		goto exit;
+	}
+
+	gccorecontext->cur_freq = gccorecontext->opp_freqs[index];
+	GCDBG(GCZONE_FREQSCALE, "frequency set to %dMHz\n",
+	      gccorecontext->cur_freq / 1000 / 1000);
+
+exit:
+	GCEXIT(GCZONE_FREQSCALE);
+}
+
+static void gcpwr_set_pulse_skipping(unsigned int pulsecount)
+{
+	union gcclockcontrol gcclockcontrol;
+
+	GCENTER(GCZONE_POWER);
+
+	/* Set the pulse skip value. */
+	gcclockcontrol.raw = 0;
+	gcclockcontrol.reg.pulsecount = pulsecount;
+
+	/* Initiate loading. */
+	gcclockcontrol.reg.pulseset = 1;
+	GCDBG(GCZONE_POWER, "pulse skip = 0x%08X\n", gcclockcontrol.raw);
+	gc_write_reg(GCREG_HI_CLOCK_CONTROL_Address, gcclockcontrol.raw);
+
+	/* Lock the value. */
+	gcclockcontrol.reg.pulseset = 0;
+	GCDBG(GCZONE_POWER, "pulse skip = 0x%08X\n", gcclockcontrol.raw);
+	gc_write_reg(GCREG_HI_CLOCK_CONTROL_Address, gcclockcontrol.raw);
+
+	GCEXIT(GCZONE_POWER);
+}
+
+static void gcpwr_enable_pulse_skipping(struct gccorecontext *gccorecontext)
+{
+	GCENTER(GCZONE_POWER);
+
+	if (!gccorecontext->clockenabled)
+		goto exit;
+
+	if (gccorecontext->pulseskipping != 1) {
+		/* Set the lowest frequency. */
+		gcpwr_scale(gccorecontext, 0);
+
+		/* Set 1 clock pulse for every 64 clocks. */
+		gcpwr_set_pulse_skipping(1);
+
+		/* Pulse skipping enabled. */
+		gccorecontext->pulseskipping = 1;
+	}
+
+	GCDBG(GCZONE_POWER, "pulse skipping %s.\n",
+	      gccorecontext->pulseskipping ? "enabled" : "disabled");
+
+exit:
+	GCEXIT(GCZONE_POWER);
+}
+
+static void gcpwr_disable_pulse_skipping(struct gccorecontext *gccorecontext)
+{
+	GCENTER(GCZONE_POWER);
+
+	if (!gccorecontext->clockenabled)
+		goto exit;
+
+	if (gccorecontext->pulseskipping != 0) {
+		/* Set the maximum frequency. */
+		gcpwr_scale(gccorecontext, gccorecontext->opp_count - 1);
+
+		/* Set full speed. */
+		gcpwr_set_pulse_skipping(64);
+
+		/* Pulse skipping disabled. */
+		gccorecontext->pulseskipping = 0;
+	}
+
+	GCDBG(GCZONE_POWER, "pulse skipping %s.\n",
+	      gccorecontext->pulseskipping ? "enabled" : "disabled");
+
+exit:
+	GCEXIT(GCZONE_POWER);
+}
+
+void gcpwr_set(struct gccorecontext *gccorecontext, enum gcpower gcpower)
+{
+	GCENTER(GCZONE_POWER);
+
+	GCLOCK(&gccorecontext->powerlock);
+
+	if (gcpower != gccorecontext->gcpower) {
+		switch (gcpower) {
+		case GCPWR_ON:
+			gcpwr_enable_clock(gccorecontext);
+			gcpwr_disable_pulse_skipping(gccorecontext);
+			break;
+
+		case GCPWR_LOW:
+			gcpwr_enable_clock(gccorecontext);
+			gcpwr_enable_pulse_skipping(gccorecontext);
+			break;
+
+		case GCPWR_OFF:
+			gcpwr_enable_pulse_skipping(gccorecontext);
+			gcpwr_disable_clock(gccorecontext);
+			break;
+
+		default:
+			GCERR("unsupported power mode %d.\n", gcpower);
+			goto exit;
+		}
+
+		GCDBG(GCZONE_POWER, "power state %d --> %d\n",
+		      gccorecontext->gcpower, gcpower);
+
+		/* Set new power state. */
+		gccorecontext->gcpower = gcpower;
+	}
+
+exit:
+	GCUNLOCK(&gccorecontext->powerlock);
+
+	GCEXIT(GCZONE_POWER);
+}
+
+enum gcpower gcpwr_get(void)
+{
+	return g_context.gcpower;
+}
+
+void gcpwr_reset(struct gccorecontext *gccorecontext)
+{
+	union gcclockcontrol gcclockcontrol;
+	union gcidle gcidle;
+
+	GCENTER(GCZONE_POWER);
+
+	GCLOCK(&gccorecontext->resetlock);
+
+	/* Read current clock control value. */
+	gcclockcontrol.raw
+		= gc_read_reg(GCREG_HI_CLOCK_CONTROL_Address);
+
+	while (true) {
+		/* Isolate the GPU. */
+		gcclockcontrol.reg.isolate = 1;
+		gc_write_reg(GCREG_HI_CLOCK_CONTROL_Address,
+				gcclockcontrol.raw);
+
+		/* Set soft reset. */
+		gcclockcontrol.reg.reset = 1;
+		gc_write_reg(GCREG_HI_CLOCK_CONTROL_Address,
+				gcclockcontrol.raw);
+
+		/* Wait for reset. */
+		msleep(1);
+
+		/* Reset soft reset bit. */
+		gcclockcontrol.reg.reset = 0;
+		gc_write_reg(GCREG_HI_CLOCK_CONTROL_Address,
+				gcclockcontrol.raw);
+
+		/* Reset GPU isolation. */
+		gcclockcontrol.reg.isolate = 0;
+		gc_write_reg(GCREG_HI_CLOCK_CONTROL_Address,
+				gcclockcontrol.raw);
+
+		/* Read idle register. */
+		gcidle.raw = gc_read_reg(GCREG_HI_IDLE_Address);
+
+		/* Try resetting again if FE not idle. */
+		if (!gcidle.reg.fe) {
+			GCERR("FE NOT IDLE\n");
+			continue;
+		}
+
+		/* Read reset register. */
+		gcclockcontrol.raw
+			= gc_read_reg(GCREG_HI_CLOCK_CONTROL_Address);
+
+		/* Try resetting again if 2D is not idle. */
+		if (!gcclockcontrol.reg.idle2d) {
+			GCERR("2D NOT IDLE\n");
+			continue;
+		}
+
+		/* GPU is idle. */
+		break;
+	}
+
+	/* Pulse skipping disabled. */
+	gccorecontext->pulseskipping = false;
+
+	GCUNLOCK(&gccorecontext->resetlock);
+
+	GCEXIT(GCZONE_POWER);
+}
+
+unsigned int gcpwr_get_speed(void)
+{
+	struct gccorecontext *gccorecontext = &g_context;
+	static const int seccount = 2;
+	unsigned int cyclecount;
+	unsigned int speedmhz = 0;
+
+	GCLOCK(&gccorecontext->powerlock);
+
+	if (gccorecontext->gcpower == GCPWR_ON) {
+		/* Reset cycle counter and sleep. */
+		gc_write_reg(GC_TOTAL_CYCLES_Address, 0);
+		msleep(seccount * 1000);
+
+		/* Read the cycle counter and compute the speed. */
+		cyclecount = gc_read_reg(GC_TOTAL_CYCLES_Address);
+		speedmhz = cyclecount / 1000 / 1000 / seccount;
+	}
+
+	GCUNLOCK(&gccorecontext->powerlock);
+
+	return speedmhz;
+}
+
+/*******************************************************************************
+ * Public API.
+ */
+
+void gc_caps(struct gcicaps *gcicaps)
+{
+	struct gccorecontext *gccorecontext = &g_context;
+
+	/* Copy capabilities. */
+	gcicaps->gcmodel = gccorecontext->gcmodel;
+	gcicaps->gcrevision = gccorecontext->gcrevision;
+	gcicaps->gcdate = gccorecontext->gcdate;
+	gcicaps->gctime = gccorecontext->gctime;
+	gcicaps->gcfeatures = gccorecontext->gcfeatures;
+	gcicaps->gcfeatures0 = gccorecontext->gcfeatures0;
+	gcicaps->gcfeatures1 = gccorecontext->gcfeatures1;
+	gcicaps->gcfeatures2 = gccorecontext->gcfeatures2;
+	gcicaps->gcfeatures3 = gccorecontext->gcfeatures3;
+
+	/* Success. */
+	gcicaps->gcerror = GCERR_NONE;
+}
+
+void gc_commit(struct gcicommit *gcicommit, bool fromuser)
+{
+	struct gccorecontext *gccorecontext = &g_context;
+	struct gcmmucontext *gcmmucontext;
+	struct gcbuffer *gcbuffer;
+	unsigned int buffersize;
+	unsigned int *logical;
+	unsigned int address;
+	struct gcmopipesel *gcmopipesel;
+	struct gcschedunmap *gcschedunmap;
+	struct list_head *head;
+
+	GCENTER(GCZONE_COMMIT);
+
+	GCLOCK(&gccorecontext->mmucontextlock);
+
+	/* Validate pipe values. */
+	if ((gcicommit->entrypipe != GCPIPE_2D) &&
+		(gcicommit->entrypipe != GCPIPE_3D)) {
+		gcicommit->gcerror = GCERR_CMD_ENTRY_PIPE;
+		goto exit;
+	}
+
+	if ((gcicommit->exitpipe != GCPIPE_2D) &&
+		(gcicommit->exitpipe != GCPIPE_3D)) {
+		gcicommit->gcerror = GCERR_CMD_EXIT_PIPE;
+		goto exit;
+	}
+
+	/* Locate the client entry. */
+	gcicommit->gcerror = find_context(gccorecontext, fromuser,
+					  &gcmmucontext);
+	if (gcicommit->gcerror != GCERR_NONE)
+		goto exit;
+
+	/* Set the master table. */
+	gcicommit->gcerror = gcmmu_set_master(gccorecontext, gcmmucontext);
+	if (gcicommit->gcerror != GCERR_NONE)
+		goto exit;
+
+	/* Set the correct graphics pipe. */
+	if (gccorecontext->gcpipe != gcicommit->entrypipe) {
+		static struct gcregpipeselect gcregpipeselect[] = {
+			/* GCPIPE_UNKNOWN */
+			{ 0, 0 },
+
+			/* GCPIPE_2D */
+			{ GCREG_PIPE_SELECT_PIPE_PIPE2D, 0 },
+
+			/* GCPIPE_2D */
+			{ GCREG_PIPE_SELECT_PIPE_PIPE2D, 0 }
+		};
+
+		GCDBG(GCZONE_COMMIT, "allocating space for pipe switch.\n");
+		gcicommit->gcerror = gcqueue_alloc(gccorecontext, gcmmucontext,
+						  sizeof(struct gcmopipesel),
+						  (void **) &gcmopipesel, NULL);
+		if (gcicommit->gcerror != GCERR_NONE)
+			goto exit;
+
+		gcmopipesel->pipesel_ldst = gcmopipesel_pipesel_ldst;
+		gcmopipesel->pipesel.reg
+			= gcregpipeselect[gcicommit->entrypipe];
+	}
+
+	/* Update the current pipe. */
+	gccorecontext->gcpipe = gcicommit->exitpipe;
+
+	/* Go through all buffers one at a time. */
+	list_for_each(head, &gcicommit->buffer) {
+		gcbuffer = list_entry(head, struct gcbuffer, link);
+		GCDBG(GCZONE_COMMIT, "gcbuffer = 0x%08X\n",
+		      (unsigned int) gcbuffer);
+
+		/* Flush MMU. */
+		gcmmu_flush(gccorecontext, gcmmucontext);
+
+		/* Compute the size of the command buffer. */
+		buffersize
+			= (unsigned char *) gcbuffer->tail
+			- (unsigned char *) gcbuffer->head;
+
+		GCDBG(GCZONE_COMMIT, "buffersize = %d\n", buffersize);
+
+		/* Reserve command buffer space. */
+		GCDBG(GCZONE_COMMIT, "allocating command buffer space.\n");
+		gcicommit->gcerror = gcqueue_alloc(gccorecontext, gcmmucontext,
+						  buffersize,
+						  (void **) &logical,
+						  &address);
+		if (gcicommit->gcerror != GCERR_NONE)
+			goto exit;
+
+		if (fromuser) {
+			/* Copy command buffer. */
+			if (copy_from_user(logical, gcbuffer->head,
+						buffersize)) {
+				GCERR("failed to read data.\n");
+				gcicommit->gcerror = GCERR_USER_READ;
+				goto exit;
+			}
+		} else {
+			memcpy(logical, gcbuffer->head, buffersize);
+		}
+
+		/* Process fixups. */
+		gcicommit->gcerror = gcmmu_fixup(&gcbuffer->fixup, logical);
+		if (gcicommit->gcerror != GCERR_NONE)
+			goto exit;
+	}
+
+	/* Add the callback. */
+	if (gcicommit->callback != NULL) {
+		gcicommit->gcerror = gcqueue_callback(gccorecontext,
+						     gcmmucontext,
+						     gcicommit->callback,
+						     gcicommit->callbackparam);
+		if (gcicommit->gcerror != GCERR_NONE)
+			goto exit;
+	}
+
+	/* Process unmappings. */
+	list_for_each(head, &gcicommit->unmap) {
+		gcschedunmap = list_entry(head, struct gcschedunmap, link);
+		gcicommit->gcerror = gcqueue_schedunmap(gccorecontext,
+						       gcmmucontext,
+						       gcschedunmap->handle);
+		if (gcicommit->gcerror != GCERR_NONE)
+			goto exit;
+	}
+
+	/* Execute the buffer. */
+	gcicommit->gcerror = gcqueue_execute(gccorecontext, false,
+					     gcicommit->asynchronous);
+
+exit:
+	GCUNLOCK(&gccorecontext->mmucontextlock);
+
+	GCEXITARG(GCZONE_COMMIT, "gc%s = 0x%08X\n",
+		(gcicommit->gcerror == GCERR_NONE) ? "result" : "error",
+		gcicommit->gcerror);
+}
+EXPORT_SYMBOL(gc_commit);
+
+void gc_map(struct gcimap *gcimap, bool fromuser)
+{
+	struct gccorecontext *gccorecontext = &g_context;
+	struct gcmmucontext *gcmmucontext;
+	struct gcmmuphysmem mem;
+	struct gcmmuarena *mapped = NULL;
+
+	GCENTER(GCZONE_MAPPING);
+
+	GCLOCK(&gccorecontext->mmucontextlock);
+
+	/* Locate the client entry. */
+	gcimap->gcerror = find_context(gccorecontext,
+				       fromuser,
+				       &gcmmucontext);
+	if (gcimap->gcerror != GCERR_NONE)
+		goto exit;
+
+	GCDBG(GCZONE_MAPPING, "map client buffer\n");
+
+	/* Initialize the mapping parameters. */
+	if (gcimap->pagearray == NULL) {
+		mem.base = ((u32) gcimap->buf.logical) & ~(PAGE_SIZE - 1);
+		mem.offset = ((u32) gcimap->buf.logical) & (PAGE_SIZE - 1);
+		mem.pages = NULL;
+
+		GCDBG(GCZONE_MAPPING, "  logical = 0x%08X\n",
+		      (unsigned int) gcimap->buf.logical);
+	} else {
+		mem.base = 0;
+		mem.offset = gcimap->buf.offset;
+		mem.pages = gcimap->pagearray;
+
+		GCDBG(GCZONE_MAPPING, "  pagearray = 0x%08X\n",
+		      (unsigned int) gcimap->pagearray);
+	}
+
+	GCDBG(GCZONE_MAPPING, "  size = %d\n", gcimap->size);
+
+	mem.count = DIV_ROUND_UP(gcimap->size + mem.offset, PAGE_SIZE);
+	mem.pagesize = gcimap->pagesize ? gcimap->pagesize : PAGE_SIZE;
+
+	/* Map the buffer. */
+	gcimap->gcerror = gcmmu_map(gccorecontext, gcmmucontext, &mem, &mapped);
+	if (gcimap->gcerror != GCERR_NONE)
+		goto exit;
+
+	gcimap->handle = (unsigned int) mapped;
+
+	GCDBG(GCZONE_MAPPING, "  mapped address = 0x%08X\n", mapped->address);
+	GCDBG(GCZONE_MAPPING, "  handle = 0x%08X\n", (unsigned int) mapped);
+
+exit:
+	GCUNLOCK(&gccorecontext->mmucontextlock);
+
+	GCEXITARG(GCZONE_MAPPING, "gc%s = 0x%08X\n",
+		(gcimap->gcerror == GCERR_NONE) ? "result" : "error",
+		gcimap->gcerror);
+}
+EXPORT_SYMBOL(gc_map);
+
+void gc_unmap(struct gcimap *gcimap, bool fromuser)
+{
+	struct gccorecontext *gccorecontext = &g_context;
+	struct gcmmucontext *gcmmucontext;
+
+	GCENTER(GCZONE_MAPPING);
+
+	GCLOCK(&gccorecontext->mmucontextlock);
+
+	/* Locate the client entry. */
+	gcimap->gcerror = find_context(gccorecontext,
+				       fromuser,
+				       &gcmmucontext);
+	if (gcimap->gcerror != GCERR_NONE)
+		goto exit;
+
+	GCDBG(GCZONE_MAPPING, "unmap client buffer\n");
+	GCDBG(GCZONE_MAPPING, "  handle = 0x%08X\n", gcimap->handle);
+
+	/* Schedule unmapping. */
+	gcimap->gcerror = gcqueue_schedunmap(gccorecontext, gcmmucontext,
+					    gcimap->handle);
+	if (gcimap->gcerror != GCERR_NONE)
+		goto exit;
+
+	/* Execute the buffer. */
+	gcimap->gcerror = gcqueue_execute(gccorecontext, false, false);
+	if (gcimap->gcerror != GCERR_NONE)
+		goto exit;
+
+	/* Invalidate the handle. */
+	gcimap->handle = ~0U;
+
+exit:
+	GCUNLOCK(&gccorecontext->mmucontextlock);
+
+	GCEXITARG(GCZONE_MAPPING, "gc%s = 0x%08X\n",
+		(gcimap->gcerror == GCERR_NONE) ? "result" : "error",
+		gcimap->gcerror);
+}
+EXPORT_SYMBOL(gc_unmap);
+
+void gc_callback(struct gcicallbackarm *gcicallbackarm, bool fromuser)
+{
+	struct gccorecontext *gccorecontext = &g_context;
+	struct gcmmucontext *gcmmucontext;
+
+	GCENTER(GCZONE_CALLBACK);
+
+	GCLOCK(&gccorecontext->mmucontextlock);
+
+	/* Locate the client entry. */
+	gcicallbackarm->gcerror = find_context(gccorecontext, fromuser,
+					       &gcmmucontext);
+	if (gcicallbackarm->gcerror != GCERR_NONE)
+		goto exit;
+
+	/* Schedule callback. */
+	gcicallbackarm->gcerror
+		= gcqueue_callback(gccorecontext,
+				   gcmmucontext,
+				   gcicallbackarm->callback,
+				   gcicallbackarm->callbackparam);
+	if (gcicallbackarm->gcerror != GCERR_NONE)
+		goto exit;
+
+exit:
+	GCUNLOCK(&gccorecontext->mmucontextlock);
+
+	GCEXITARG(GCZONE_CALLBACK, "gc%s = 0x%08X\n",
+		  (gcicallbackarm->gcerror == GCERR_NONE) ? "result" : "error",
+		   gcicallbackarm->gcerror);
+}
+EXPORT_SYMBOL(gc_callback);
+
+void gc_release(void)
+{
+	struct gccorecontext *gccorecontext = &g_context;
+	struct list_head *ctxhead;
+	struct gcmmucontext *temp = NULL;
+	pid_t pid;
+
+	GCENTER(GCZONE_CONTEXT);
+
+	GCLOCK(&gccorecontext->mmucontextlock);
+
+	pid = current->tgid;
+	GCDBG(GCZONE_CONTEXT, "scanning context records for pid %d.\n", pid);
+
+	list_for_each(ctxhead, &gccorecontext->mmuctxlist) {
+		temp = list_entry(ctxhead, struct gcmmucontext, link);
+		if (temp->pid == pid) {
+			GCDBG(GCZONE_CONTEXT, "context is found @ 0x%08X\n",
+			      (unsigned int) temp);
+
+			gcmmu_destroy_context(gccorecontext, temp);
+			list_move(ctxhead, &gccorecontext->mmuctxvac);
+			break;
+		}
+	}
+
+	GCUNLOCK(&gccorecontext->mmucontextlock);
+
+	GCEXIT(GCZONE_CONTEXT);
+}
+EXPORT_SYMBOL(gc_release);
+
+static int gc_probe_opp(struct platform_device *pdev)
+{
+	int i;
+	unsigned int size;
+	unsigned long freq = 0;
+	struct gccorecontext *gccorecontext = &g_context;
+
+	/* Query supported OPPs. */
+	rcu_read_lock();
+
+	gccorecontext->opp_count = opp_get_opp_count(&pdev->dev);
+	if (gccorecontext->opp_count <= 0) {
+		gccorecontext->opp_count = 0;
+		goto done;
+	}
+
+	size = gccorecontext->opp_count * sizeof(unsigned long);
+	gccorecontext->opp_freqs = kzalloc(size, GFP_ATOMIC);
+	if (!gccorecontext->opp_freqs) {
+		gccorecontext->opp_count = 0;
+		goto done;
+	}
+
+	GCDBG(GCZONE_FREQSCALE, "frequency scaling table:\n");
+
+	for (i = 0; i < gccorecontext->opp_count; i++) {
+		struct opp *opp = opp_find_freq_ceil(&pdev->dev, &freq);
+		if (IS_ERR_OR_NULL(opp)) {
+			gccorecontext->opp_count = i;
+			goto done;
+		}
+
+		/* Set freq, prepare to next. */
+		gccorecontext->opp_freqs[i] = freq++;
+		GCDBG(GCZONE_FREQSCALE, "  [%d] 0x%08X\n",
+		      i, gccorecontext->opp_freqs[i]);
+	}
+
+done:
+	rcu_read_unlock();
+	gcpwr_set(gccorecontext, GCPWR_LOW);
+	return 0;
+}
+
+static int gc_probe(struct platform_device *pdev)
+{
+	struct gccorecontext *gccorecontext = &g_context;
+
+	GCENTER(GCZONE_PROBE);
+
+	gccorecontext->bb2ddevice = &pdev->dev;
+	gccorecontext->plat = (struct omap_gcx_platform_data *)
+			       pdev->dev.platform_data;
+	gccorecontext->regbase = gccorecontext->plat->regbase;
+	gccorecontext->irqline = platform_get_irq(pdev, pdev->id);
+	gccorecontext->device = &pdev->dev;
+
+	pm_runtime_enable(gccorecontext->device);
+	gccorecontext->plat->get_context_loss_count(gccorecontext->device);
+
+	gc_probe_opp(pdev);
+
+	pm_runtime_get_sync(gccorecontext->device);
+
+	gccorecontext->gcmodel = gc_read_reg(GC_CHIP_ID_Address);
+	gccorecontext->gcrevision = gc_read_reg(GC_CHIP_REV_Address);
+	gccorecontext->gcdate = gc_read_reg(GC_CHIP_DATE_Address);
+	gccorecontext->gctime = gc_read_reg(GC_CHIP_TIME_Address);
+	gccorecontext->gcfeatures.raw = gc_read_reg(GC_FEATURES_Address);
+	gccorecontext->gcfeatures0.raw = gc_read_reg(GC_FEATURES0_Address);
+	gccorecontext->gcfeatures1.raw = gc_read_reg(GC_FEATURES1_Address);
+	gccorecontext->gcfeatures2.raw = gc_read_reg(GC_FEATURES2_Address);
+	gccorecontext->gcfeatures3.raw = gc_read_reg(GC_FEATURES3_Address);
+
+	GCDBG(GCZONE_PROBE, "GPU IDENTITY:\n");
+	GCDBG(GCZONE_PROBE, "  model=%X\n", gccorecontext->gcmodel);
+	GCDBG(GCZONE_PROBE, "  revision=%X\n", gccorecontext->gcrevision);
+	GCDBG(GCZONE_PROBE, "  date=%X\n", gccorecontext->gcdate);
+	GCDBG(GCZONE_PROBE, "  time=%X\n", gccorecontext->gctime);
+	GCDBG(GCZONE_PROBE, "  features=0x%08X\n", gccorecontext->gcfeatures);
+	GCDBG(GCZONE_PROBE, "  features0=0x%08X\n", gccorecontext->gcfeatures0);
+	GCDBG(GCZONE_PROBE, "  features1=0x%08X\n", gccorecontext->gcfeatures1);
+	GCDBG(GCZONE_PROBE, "  features2=0x%08X\n", gccorecontext->gcfeatures2);
+	GCDBG(GCZONE_PROBE, "  features3=0x%08X\n", gccorecontext->gcfeatures3);
+
+	pm_runtime_put_sync(gccorecontext->device);
+
+	GCEXIT(GCZONE_PROBE);
+	return 0;
+}
+
+static int gc_remove(struct platform_device *pdev)
+{
+	kfree(g_context.opp_freqs);
+	return 0;
+}
+
+#if GC_ENABLE_SUSPEND
+static int gc_suspend(struct platform_device *pdev, pm_message_t s)
+{
+	GCENTER(GCZONE_POWER);
+	gcqueue_wait_idle(&g_context);
+	GCEXIT(GCZONE_POWER);
+	return 0;
+}
+
+static int gc_resume(struct platform_device *pdev)
+{
+	GCENTER(GCZONE_POWER);
+	GCEXIT(GCZONE_POWER);
+	return 0;
+}
+#endif
+
+static struct platform_driver plat_drv = {
+	.probe = gc_probe,
+	.remove = gc_remove,
+#if GC_ENABLE_SUSPEND
+	.suspend = gc_suspend,
+	.resume = gc_resume,
+#endif
+	.driver = {
+		.owner = THIS_MODULE,
+		.name = "gccore",
+	},
+};
+
+#if CONFIG_HAS_EARLYSUSPEND
+#include <linux/earlysuspend.h>
+static void gc_early_suspend(struct early_suspend *h)
+{
+	GCENTER(GCZONE_POWER);
+	gcqueue_wait_idle(&g_context);
+	GCEXIT(GCZONE_POWER);
+}
+
+static void gc_late_resume(struct early_suspend *h)
+{
+	GCENTER(GCZONE_POWER);
+	GCEXIT(GCZONE_POWER);
+}
+
+static struct early_suspend early_suspend_info = {
+	.suspend = gc_early_suspend,
+	.resume = gc_late_resume,
+	.level = EARLY_SUSPEND_LEVEL_DISABLE_FB,
+};
+#endif
+
+
+/*******************************************************************************
+ * Driver init/shutdown.
+ */
+
+static int gc_init(struct gccorecontext *gccorecontext);
+static void gc_exit(struct gccorecontext *gccorecontext);
+
+static int gc_init(struct gccorecontext *gccorecontext)
+{
+	int result;
+
+	GCENTER(GCZONE_INIT);
+
+	/* check if hardware is available */
+	if (!cpu_is_omap447x()) {
+		GCDBG(GCZONE_INIT, "gcx hardware is not present\n");
+		goto exit;
+	}
+
+	/* Initialize data structutres. */
+	GCLOCK_INIT(&gccorecontext->powerlock);
+	GCLOCK_INIT(&gccorecontext->resetlock);
+	GCLOCK_INIT(&gccorecontext->mmucontextlock);
+	INIT_LIST_HEAD(&gccorecontext->mmuctxlist);
+	INIT_LIST_HEAD(&gccorecontext->mmuctxvac);
+
+	/* Pulse skipping isn't known. */
+	gccorecontext->pulseskipping = -1;
+
+	/* Initialize MMU. */
+	if (gcmmu_init(gccorecontext) != GCERR_NONE) {
+		GCERR("failed to initialize MMU.\n");
+		result = -EINVAL;
+		goto fail;
+	}
+
+	result = platform_driver_register(&plat_drv);
+	if (result < 0) {
+		GCERR("failed to register platform driver.\n");
+		goto fail;
+	}
+	gccorecontext->platdriver = true;
+
+#if CONFIG_HAS_EARLYSUSPEND
+	register_early_suspend(&early_suspend_info);
+#endif
+
+	/* Initialize the command buffer. */
+	if (gcqueue_start(gccorecontext) != GCERR_NONE) {
+		GCERR("failed to initialize command buffer.\n");
+		result = -EINVAL;
+		goto fail;
+	}
+
+	/* Create debugfs entry. */
+	gc_debug_init();
+
+exit:
+	GCEXIT(GCZONE_INIT);
+	return 0;
+
+fail:
+	gc_exit(gccorecontext);
+
+	GCEXITARG(GCZONE_INIT, "result = %d\n", result);
+	return result;
+}
+
+static void gc_exit(struct gccorecontext *gccorecontext)
+{
+	GCENTER(GCZONE_INIT);
+
+	if (cpu_is_omap447x()) {
+		/* Stop command queue thread. */
+		gcqueue_stop(gccorecontext);
+
+		/* Destroy MMU. */
+		destroy_mmu_context(gccorecontext);
+		gcmmu_exit(gccorecontext);
+
+		/* Disable power. */
+		pm_runtime_disable(gccorecontext->device);
+
+		if (gccorecontext->platdriver) {
+			platform_driver_unregister(&plat_drv);
+			gccorecontext->platdriver = false;
+		}
+
+#if CONFIG_HAS_EARLYSUSPEND
+		unregister_early_suspend(&early_suspend_info);
+#endif
+
+		gc_debug_shutdown();
+
+		GCLOCK_DESTROY(&gccorecontext->mmucontextlock);
+		GCLOCK_DESTROY(&gccorecontext->resetlock);
+		GCLOCK_DESTROY(&gccorecontext->powerlock);
+	}
+
+	GCEXIT(GCZONE_PROBE);
+}
+
+static int __init gc_init_wrapper(void)
+{
+	GCDBG_INIT();
+
+	GCDBG_REGISTER(core,  GCZONE_NONE);
+	GCDBG_REGISTER(mem,   GCZONE_NONE);
+	GCDBG_REGISTER(mmu,   GCZONE_NONE);
+	GCDBG_REGISTER(queue, GCZONE_NONE);
+
+	return gc_init(&g_context);
+}
+
+static void __exit gc_exit_wrapper(void)
+{
+	gc_exit(&g_context);
+	GCDBG_EXIT();
+}
+
+MODULE_LICENSE("GPL v2");
+MODULE_AUTHOR("www.vivantecorp.com");
+MODULE_AUTHOR("www.ti.com");
+module_init(gc_init_wrapper);
+module_exit(gc_exit_wrapper);
diff --git a/drivers/misc/gcx/gccore/gcmain.h b/drivers/misc/gcx/gccore/gcmain.h
new file mode 100644
index 0000000..e2931d4
--- /dev/null
+++ b/drivers/misc/gcx/gccore/gcmain.h
@@ -0,0 +1,114 @@
+/*
+ * gcmain.h
+ *
+ * Copyright (C) 2010-2011 Vivante Corporation.
+ *
+ * This package is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#ifndef GCMAIN_H
+#define GCMAIN_H
+
+#include <linux/gcx.h>
+#include <linux/gccore.h>
+#include "gcmmu.h"
+
+#define GC_DEV_NAME	"gccore"
+
+
+/*******************************************************************************
+ * Power management modes.
+ */
+
+enum gcpower {
+	GCPWR_UNKNOWN,
+	GCPWR_ON,
+	GCPWR_LOW,
+	GCPWR_OFF
+};
+
+
+/*******************************************************************************
+ * Driver context.
+ */
+
+struct omap_gcx_platform_data;
+
+struct gccorecontext {
+	/* GPU IRQ line. */
+	int irqline;
+
+	/* Capabilities and characteristics. */
+	unsigned int gcmodel;
+	unsigned int gcrevision;
+	unsigned int gcdate;
+	unsigned int gctime;
+	union gcfeatures gcfeatures;
+	union gcfeatures0 gcfeatures0;
+	union gcfeatures1 gcfeatures1;
+	union gcfeatures2 gcfeatures2;
+	union gcfeatures3 gcfeatures3;
+
+	/* Virtual pointer to the GPU register bank. */
+	void *regbase;
+
+	/* Platform driver install flag. */
+	bool platdriver;
+	struct omap_gcx_platform_data *plat;
+
+	/* Pointers to the gccore and BB2D devices. */
+	struct device *device;
+	struct device *bb2ddevice;
+
+	/* Current power mode. */
+	enum gcpower gcpower;
+	GCLOCK_TYPE powerlock;
+	GCLOCK_TYPE resetlock;
+
+	/* Current graphics pipe. */
+	enum gcpipe gcpipe;
+
+	/* Power mode flags. */
+	bool clockenabled;
+	int pulseskipping;
+
+	/* MMU and command buffer managers. */
+	struct gcmmu gcmmu;
+	struct gcqueue gcqueue;
+
+	/* MMU context lists. */
+	struct list_head mmuctxlist;
+	struct list_head mmuctxvac;
+	GCLOCK_TYPE mmucontextlock;
+
+	/* Device frequency scaling. */
+	int opp_count;
+	unsigned long *opp_freqs;
+	unsigned long  cur_freq;
+};
+
+
+/*******************************************************************************
+ * Register access.
+ */
+
+unsigned int gc_read_reg(unsigned int address);
+void gc_write_reg(unsigned int address, unsigned int data);
+
+
+/*******************************************************************************
+ * Power management.
+ */
+
+enum gcpower gcpwr_get(void);
+void gcpwr_set(struct gccorecontext *gccorecontext, enum gcpower gcpower);
+void gcpwr_reset(struct gccorecontext *gccorecontext);
+unsigned int gcpwr_get_speed(void);
+
+#endif
diff --git a/drivers/misc/gcx/gccore/gcmem.c b/drivers/misc/gcx/gccore/gcmem.c
new file mode 100644
index 0000000..b3b01d4
--- /dev/null
+++ b/drivers/misc/gcx/gccore/gcmem.c
@@ -0,0 +1,201 @@
+/*
+ * gcmain.c
+ *
+ * Copyright (C) 2010-2011 Vivante Corporation.
+ *
+ * This package is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#include <linux/pagemap.h>
+#include <linux/dma-mapping.h>
+#include "gcmain.h"
+
+#define GCZONE_NONE		0
+#define GCZONE_ALL		(~0U)
+#define GCZONE_CACHED		(1 << 0)
+#define GCZONE_NONCACHED	(1 << 1)
+#define GCZONE_FLUSH		(1 << 2)
+
+GCDBG_FILTERDEF(mem, GCZONE_NONE,
+		"cached",
+		"noncached",
+		"flush")
+
+enum gcerror gc_alloc_noncached(struct gcpage *p, unsigned int size)
+{
+	enum gcerror gcerror;
+
+	GCENTERARG(GCZONE_NONCACHED, "p = 0x%08X\n", (unsigned int) p);
+
+	p->pages = NULL;
+	p->order = 0;
+	p->size = (size + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1);
+	p->logical = NULL;
+	p->physical = ~0UL;
+
+	GCDBG(GCZONE_NONCACHED, "requested size=%d\n", size);
+	GCDBG(GCZONE_NONCACHED, "aligned size=%d\n", p->size);
+
+	p->logical = dma_alloc_coherent(NULL, p->size, &p->physical,
+						GFP_KERNEL);
+	if (!p->logical) {
+		GCERR("failed to allocate memory\n");
+		gcerror = GCERR_OOPM;
+		goto exit;
+	}
+
+	GCDBG(GCZONE_NONCACHED, "logical=0x%08X\n",
+		(unsigned int) p->logical);
+	GCDBG(GCZONE_NONCACHED, "physical=0x%08X\n",
+		(unsigned int) p->physical);
+
+	GCEXIT(GCZONE_NONCACHED);
+	return GCERR_NONE;
+
+exit:
+	gc_free_noncached(p);
+
+	GCEXITARG(GCZONE_NONCACHED, "gcerror = 0x%08X\n", gcerror);
+	return gcerror;
+}
+
+void gc_free_noncached(struct gcpage *p)
+{
+	GCENTERARG(GCZONE_NONCACHED, "p = 0x%08X\n", (unsigned int) p);
+
+	if (p->logical != NULL) {
+		dma_free_coherent(NULL, p->size, p->logical, p->physical);
+		p->logical = NULL;
+	}
+
+	p->physical = ~0UL;
+	p->size = 0;
+
+	GCEXIT(GCZONE_NONCACHED);
+}
+
+enum gcerror gc_alloc_cached(struct gcpage *p, unsigned int size)
+{
+	enum gcerror gcerror;
+	struct page *pages;
+	int count;
+
+	GCENTERARG(GCZONE_CACHED, "p = 0x%08X\n", (unsigned int) p);
+
+	p->order = get_order(size);
+	p->pages = NULL;
+	p->size = (1 << p->order) * PAGE_SIZE;
+	p->logical = NULL;
+	p->physical = ~0UL;
+
+	GCDBG(GCZONE_CACHED, "requested size=%d\n", size);
+	GCDBG(GCZONE_CACHED, "aligned size=%d\n", p->size);
+
+	p->pages = alloc_pages(GFP_KERNEL, p->order);
+	if (p->pages == NULL) {
+		GCERR("failed to allocate memory\n");
+		gcerror = GCERR_OOPM;
+		goto exit;
+	}
+
+	p->physical = page_to_phys(p->pages);
+	p->logical = (unsigned int *) page_address(p->pages);
+
+	if (p->logical == NULL) {
+		GCERR("failed to retrieve page virtual address\n");
+		gcerror = GCERR_PMMAP;
+		goto exit;
+	}
+
+	/* Reserve pages. */
+	pages = p->pages;
+	count = p->size / PAGE_SIZE;
+
+	while (count--)
+		SetPageReserved(pages++);
+
+	GCDBG(GCZONE_CACHED, "page array=0x%08X\n", (unsigned int) p->pages);
+	GCDBG(GCZONE_CACHED, "logical=0x%08X\n", (unsigned int) p->logical);
+	GCDBG(GCZONE_CACHED, "physical=0x%08X\n", (unsigned int) p->physical);
+
+	GCEXIT(GCZONE_CACHED);
+	return GCERR_NONE;
+
+exit:
+	gc_free_cached(p);
+
+	GCEXITARG(GCZONE_CACHED, "gcerror = 0x%08X\n", gcerror);
+	return gcerror;
+}
+
+void gc_free_cached(struct gcpage *p)
+{
+	GCENTERARG(GCZONE_CACHED, "p = 0x%08X\n", (unsigned int) p);
+
+	GCDBG(GCZONE_CACHED, "page array=0x%08X\n", (unsigned int) p->pages);
+	GCDBG(GCZONE_CACHED, "logical=0x%08X\n", (unsigned int) p->logical);
+	GCDBG(GCZONE_CACHED, "physical=0x%08X\n", (unsigned int) p->physical);
+	GCDBG(GCZONE_CACHED, "size=%d\n", p->size);
+
+	if (p->logical != NULL) {
+		struct page *pages;
+		int count;
+
+		pages = p->pages;
+		count = p->size / PAGE_SIZE;
+
+		while (count--)
+			ClearPageReserved(pages++);
+
+		p->logical = NULL;
+	}
+
+	if (p->pages != NULL) {
+		__free_pages(p->pages, p->order);
+		p->pages = NULL;
+	}
+
+	p->physical = ~0UL;
+	p->order = 0;
+	p->size = 0;
+
+	GCEXIT(GCZONE_CACHED);
+}
+
+void gc_flush_cached(struct gcpage *p)
+{
+	GCENTERARG(GCZONE_FLUSH, "p = 0x%08X\n", (unsigned int) p);
+
+	dmac_flush_range(p->logical, (unsigned char *) p->logical + p->size);
+	outer_flush_range(p->physical, p->physical + p->size);
+
+	GCEXIT(GCZONE_FLUSH);
+}
+
+void gc_flush_region(unsigned int physical, void *logical,
+			unsigned int offset, unsigned int size)
+{
+	unsigned char *startlog;
+	unsigned int startphys;
+
+	GCENTER(GCZONE_FLUSH);
+
+	GCDBG(GCZONE_FLUSH, "logical=0x%08X\n", (unsigned int) logical);
+	GCDBG(GCZONE_FLUSH, "physical=0x%08X\n", physical);
+	GCDBG(GCZONE_FLUSH, "offset=%d\n", offset);
+	GCDBG(GCZONE_FLUSH, "size=%d\n", size);
+
+	startlog = (unsigned char *) logical + offset;
+	startphys = physical + offset;
+
+	dmac_flush_range(startlog, startlog + size);
+	outer_flush_range(startphys, startphys + size);
+
+	GCEXIT(GCZONE_FLUSH);
+}
diff --git a/drivers/misc/gcx/gccore/gcmem.h b/drivers/misc/gcx/gccore/gcmem.h
new file mode 100644
index 0000000..09c55e7
--- /dev/null
+++ b/drivers/misc/gcx/gccore/gcmem.h
@@ -0,0 +1,36 @@
+/*
+ * gcmem.h
+ *
+ * Copyright (C) 2010-2011 Vivante Corporation.
+ *
+ * This package is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#ifndef GCMEM_H
+#define GCMEM_H
+
+struct gcpage {
+	unsigned int order;
+	struct page *pages;
+
+	unsigned int size;
+	unsigned int physical;
+	unsigned int *logical;
+};
+
+enum gcerror gc_alloc_noncached(struct gcpage *p, unsigned int size);
+void gc_free_noncached(struct gcpage *p);
+
+enum gcerror gc_alloc_cached(struct gcpage *p, unsigned int size);
+void gc_free_cached(struct gcpage *p);
+void gc_flush_cached(struct gcpage *p);
+void gc_flush_region(unsigned int physical, void *logical,
+			unsigned int offset, unsigned int size);
+
+#endif
diff --git a/drivers/misc/gcx/gccore/gcmmu.c b/drivers/misc/gcx/gccore/gcmmu.c
new file mode 100644
index 0000000..42e68e4
--- /dev/null
+++ b/drivers/misc/gcx/gccore/gcmmu.c
@@ -0,0 +1,1297 @@
+/*
+ * gcmmu.c
+ *
+ * Copyright (C) 2010-2011 Vivante Corporation.
+ *
+ * This package is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/highmem.h>
+#include <linux/slab.h>
+#include <linux/io.h>
+#include <linux/pagemap.h>
+#include <linux/sched.h>
+#include "gcmain.h"
+
+#define GCZONE_NONE		0
+#define GCZONE_ALL		(~0U)
+#define GCZONE_INIT		(1 << 0)
+#define GCZONE_MAPPING		(1 << 1)
+#define GCZONE_CONTEXT		(1 << 2)
+#define GCZONE_MASTER		(1 << 3)
+#define GCZONE_FIXUP		(1 << 4)
+#define GCZONE_FLUSH		(1 << 5)
+#define GCZONE_ARENA		(1 << 6)
+#define GCZONE_DUMPMAP		(1 << 7)
+#define GCZONE_DUMPUNMAP	(1 << 8)
+
+GCDBG_FILTERDEF(mmu, GCZONE_NONE,
+		"init",
+		"mapping",
+		"context",
+		"master",
+		"fixup",
+		"flush",
+		"arena",
+		"dumpmap",
+		"dumpunmap")
+
+
+/*******************************************************************************
+ * Internal definitions.
+ */
+
+/* Slave table preallocation block; can describe an array of slave tables. */
+struct gcmmustlbblock {
+	/* Slave table allocation. */
+	struct gcpage pages;
+
+	/* Next block of preallocated slave memory. */
+	struct gcmmustlbblock *next;
+};
+
+
+/*******************************************************************************
+ * Call back to enable MMU.
+ */
+
+static void event_enable_mmu(struct gcevent *gcevent, unsigned int *flags)
+{
+	GCENTER(GCZONE_INIT);
+
+	/*
+	* Enable MMU. For security reasons, once it is enabled,
+	* the only way to disable is to reset the system.
+	*/
+	gc_write_reg(
+		GCREG_MMU_CONTROL_Address,
+		GCSETFIELDVAL(0, GCREG_MMU_CONTROL, ENABLE, ENABLE));
+
+	/* After MMU command buffer is processed, FE will stop.
+	 * Let the control thread know that FE needs to be restarted. */
+	if (flags == NULL)
+		GCERR("flags are not set.\n");
+	else
+		*flags |= GC_CMDBUF_START_FE;
+
+	GCEXIT(GCZONE_INIT);
+}
+
+
+/*******************************************************************************
+ * Arena record management.
+ */
+
+static enum gcerror get_arena(struct gcmmu *gcmmu, struct gcmmuarena **arena)
+{
+	enum gcerror gcerror = GCERR_NONE;
+	struct gcmmuarena *temp;
+
+	GCENTER(GCZONE_ARENA);
+
+	GCLOCK(&gcmmu->lock);
+
+	if (list_empty(&gcmmu->vacarena)) {
+		temp = kmalloc(sizeof(struct gcmmuarena), GFP_KERNEL);
+		if (temp == NULL) {
+			GCERR("arena entry allocation failed.\n");
+			gcerror = GCERR_SETGRP(GCERR_OODM,
+						GCERR_MMU_ARENA_ALLOC);
+			goto exit;
+		}
+	} else {
+		struct list_head *head;
+		head = gcmmu->vacarena.next;
+		temp = list_entry(head, struct gcmmuarena, link);
+		list_del(head);
+	}
+
+	*arena = temp;
+
+exit:
+	GCUNLOCK(&gcmmu->lock);
+
+	GCEXITARG(GCZONE_ARENA, "gc%s = 0x%08X\n",
+		(gcerror == GCERR_NONE) ? "result" : "error", gcerror);
+	return gcerror;
+}
+
+static inline bool siblings(struct list_head *head,
+			    struct list_head *arenahead1,
+			    struct list_head *arenahead2)
+{
+	struct gcmmuarena *arena1;
+	struct gcmmuarena *arena2;
+
+	if ((arenahead1 == head) || (arenahead2 == head))
+		return false;
+
+	arena1 = list_entry(arenahead1, struct gcmmuarena, link);
+	arena2 = list_entry(arenahead2, struct gcmmuarena, link);
+
+	return (arena1->end.absolute == arena2->start.absolute) ? true : false;
+}
+
+/*******************************************************************************
+ * Slave table allocation management.
+ */
+
+static enum gcerror allocate_slave(struct gcmmucontext *gcmmucontext,
+				   union gcmmuloc index)
+{
+	enum gcerror gcerror;
+	struct gcmmustlbblock *block = NULL;
+	struct gcmmustlb *slave;
+	unsigned int *mtlblogical;
+	unsigned int prealloccount;
+	unsigned int preallocsize;
+	unsigned int preallocentries;
+	unsigned int physical;
+	unsigned int *logical;
+	unsigned int i;
+
+	GCENTER(GCZONE_MAPPING);
+
+	/* Allocate a new prealloc block wrapper. */
+	block = kmalloc(sizeof(struct gcmmustlbblock), GFP_KERNEL);
+	if (block == NULL) {
+		GCERR("failed to allocate slave page table wrapper\n");
+		gcerror = GCERR_SETGRP(GCERR_OODM,
+				       GCERR_MMU_STLB_ALLOC);
+		goto exit;
+	}
+
+	/* Determine the number and the size of tables to allocate. */
+	prealloccount = min(GCMMU_STLB_PREALLOC_COUNT,
+			    GCMMU_MTLB_ENTRY_NUM - index.loc.mtlb);
+
+	preallocsize = prealloccount * GCMMU_STLB_SIZE;
+	preallocentries = prealloccount * GCMMU_STLB_ENTRY_NUM;
+
+	GCDBG(GCZONE_MAPPING, "preallocating %d slave tables.\n",
+	      prealloccount);
+
+	/* Allocate slave table pool. */
+	gcerror = gc_alloc_cached(&block->pages, preallocsize);
+	if (gcerror != GCERR_NONE) {
+		GCERR("failed to allocate slave page table\n");
+		gcerror = GCERR_SETGRP(gcerror, GCERR_MMU_STLB_ALLOC);
+		goto exit;
+	}
+
+	/* Add the block to the list. */
+	block->next = gcmmucontext->slavealloc;
+	gcmmucontext->slavealloc = block;
+
+	/* Get shortcuts to the pointers. */
+	physical = block->pages.physical;
+	logical = block->pages.logical;
+
+	/* Invalidate all slave entries. */
+	for (i = 0; i < preallocentries; i += 1)
+		logical[i] = GCMMU_STLB_ENTRY_VACANT;
+
+	/* Init the slaves. */
+	slave = &gcmmucontext->slave[index.loc.mtlb];
+	mtlblogical = &gcmmucontext->master.logical[index.loc.mtlb];
+
+	for (i = 0; i < prealloccount; i += 1) {
+		mtlblogical[i]
+			= (physical & GCMMU_MTLB_SLAVE_MASK)
+			| GCMMU_MTLB_4K_PAGE
+			| GCMMU_MTLB_EXCEPTION
+			| GCMMU_MTLB_PRESENT;
+
+		slave[i].physical = physical;
+		slave[i].logical = logical;
+
+		physical += GCMMU_STLB_SIZE;
+		logical = (unsigned int *)
+			((unsigned char *) logical + GCMMU_STLB_SIZE);
+	}
+
+	/* Flush CPU cache. */
+	gc_flush_region(gcmmucontext->master.physical,
+			gcmmucontext->master.logical,
+			index.loc.mtlb * sizeof(unsigned int),
+			prealloccount * sizeof(unsigned int));
+
+	GCEXIT(GCZONE_MAPPING);
+	return GCERR_NONE;
+
+exit:
+	if (block != NULL)
+		kfree(block);
+
+	GCEXITARG(GCZONE_MAPPING, "gc%s = 0x%08X\n",
+		(gcerror == GCERR_NONE) ? "result" : "error", gcerror);
+	return gcerror;
+}
+
+/*******************************************************************************
+ * Physical page array generation.
+ */
+
+static enum gcerror virt2phys(unsigned int logical, pte_t *physical)
+{
+	pgd_t *pgd;	/* Page Global Directory (PGD). */
+	pmd_t *pmd;	/* Page Middle Directory (PMD). */
+	pte_t *pte;	/* Page Table Entry (PTE). */
+
+	/* Get the pointer to the entry in PGD for the address. */
+	pgd = pgd_offset(current->mm, logical);
+	if (pgd_none(*pgd) || pgd_bad(*pgd))
+		return GCERR_MMU_PAGE_BAD;
+
+	/* Get the pointer to the entry in PMD for the address. */
+	pmd = pmd_offset(pgd, logical);
+	if (pmd_none(*pmd) || pmd_bad(*pmd))
+		return GCERR_MMU_PAGE_BAD;
+
+	/* Get the pointer to the entry in PTE for the address. */
+	pte = pte_offset_map(pmd, logical);
+	if ((pte == NULL) || !pte_present(*pte))
+		return GCERR_MMU_PAGE_BAD;
+
+	*physical = (*pte & PAGE_MASK) | (logical & ~PAGE_MASK);
+	return GCERR_NONE;
+}
+
+#if !defined(PFN_DOWN)
+#	define PFN_DOWN(x) \
+		((x) >> PAGE_SHIFT)
+#endif
+
+#if !defined(phys_to_pfn)
+#	define phys_to_pfn(phys) \
+		(PFN_DOWN(phys))
+#endif
+
+#if !defined(phys_to_page)
+#	define phys_to_page(paddr) \
+		(pfn_to_page(phys_to_pfn(paddr)))
+#endif
+
+static enum gcerror get_physical_pages(struct gcmmuphysmem *mem,
+				       pte_t *parray,
+				       struct gcmmuarena *arena)
+{
+	enum gcerror gcerror = GCERR_NONE;
+	struct vm_area_struct *vma;
+	struct page **pages = NULL;
+	unsigned long base, start, end;
+	unsigned int write;
+	int i, count = 0;
+
+	GCENTER(GCZONE_MAPPING);
+
+	/* Get the base address. */
+	base = mem->base;
+
+	/* Reset page descriptor array. */
+	arena->pages = NULL;
+
+	/* Store the logical pointer. */
+	arena->logical = (void *) base;
+
+	/* Compute virtual memory area limits. */
+	start = base + mem->offset;
+	end = base + mem->count * mem->pagesize;
+	GCDBG(GCZONE_MAPPING, "base = 0x%08X\n", base);
+	GCDBG(GCZONE_MAPPING, "offset = 0x%08X\n", mem->offset);
+	GCDBG(GCZONE_MAPPING, "count = %d\n", mem->count);
+	GCDBG(GCZONE_MAPPING, "start = 0x%08X\n", start);
+	GCDBG(GCZONE_MAPPING, "end = 0x%08X\n", end);
+
+	vma = find_vma(current->mm, start);
+	if (vma == NULL) {
+		gcerror = GCERR_MMU_BUFFER_BAD;
+		GCERR("failed to find VMA.\n");
+		goto exit;
+	}
+
+	GCDBG(GCZONE_MAPPING, "vm_start = 0x%08X\n", vma->vm_start);
+	GCDBG(GCZONE_MAPPING, "vm_end = 0x%08X\n", vma->vm_end);
+	if ((start < vma->vm_start) || (end > vma->vm_end)) {
+		gcerror = GCERR_MMU_BUFFER_BAD;
+		GCERR("failed to find VMA...\n");
+		goto exit;
+	}
+
+	/* Allocate page descriptor array. */
+	pages = kmalloc(mem->count * sizeof(struct page *), GFP_KERNEL);
+	if (pages == NULL) {
+		GCERR("failed to allocate page descriptor array.\n");
+		gcerror = GCERR_SETGRP(GCERR_OODM, GCERR_MMU_DESC_ALLOC);
+		goto exit;
+	}
+
+	/* Query page descriptors. */
+	write = ((vma->vm_flags & (VM_WRITE | VM_MAYWRITE)) != 0) ? 1 : 0;
+
+	down_read(&current->mm->mmap_sem);
+	count = get_user_pages(current, current->mm, base, mem->count,
+			       write, 1, pages, NULL);
+	up_read(&current->mm->mmap_sem);
+
+	if (count < 0) {
+		/* Kernel allocated buffer. */
+		for (i = 0; i < mem->count; i += 1) {
+			gcerror = virt2phys(base, &parray[i]);
+			if (gcerror != GCERR_NONE) {
+				GCERR("failed to convert virtual address.\n");
+				goto exit;
+			}
+
+			base += mem->pagesize;
+		}
+	} else if (count == mem->count) {
+		/* User allocated buffer. */
+		for (i = 0; i < mem->count; i += 1) {
+			parray[i] = page_to_phys(pages[i]);
+			if (phys_to_page(parray[i]) != pages[i]) {
+				GCERR("failed to convert page address.\n");
+				gcerror = GCERR_MMU_PAGE_BAD;
+				goto exit;
+			}
+		}
+
+		/* Set page descriptor array. */
+		arena->pages = pages;
+	} else {
+		GCERR("invalid number of pages.\n");
+		gcerror = GCERR_MMU_BUFFER_BAD;
+		goto exit;
+	}
+
+exit:
+	if (arena->pages == NULL) {
+		for (i = 0; i < count; i += 1)
+			page_cache_release(pages[i]);
+
+		if (pages != NULL)
+			kfree(pages);
+	}
+
+	GCEXIT(GCZONE_MAPPING);
+	return gcerror;
+}
+
+static void release_physical_pages(struct gcmmuarena *arena)
+{
+	unsigned int i;
+
+	if (arena->pages != NULL) {
+		for (i = 0; i < arena->count; i += 1)
+			page_cache_release(arena->pages[i]);
+
+		kfree(arena->pages);
+		arena->pages = NULL;
+	}
+}
+
+/*******************************************************************************
+ * MMU management API.
+ */
+
+enum gcerror gcmmu_init(struct gccorecontext *gccorecontext)
+{
+	enum gcerror gcerror;
+	struct gcmmu *gcmmu = &gccorecontext->gcmmu;
+
+	GCENTER(GCZONE_INIT);
+
+	/* Initialize access lock. */
+	GCLOCK_INIT(&gcmmu->lock);
+
+	/* Allocate one page. */
+	gcerror = gc_alloc_noncached(&gcmmu->gcpage, PAGE_SIZE);
+	if (gcerror != GCERR_NONE) {
+		GCERR("failed to allocate MMU management buffer.\n");
+		gcerror = GCERR_SETGRP(gcerror, GCERR_MMU_SAFE_ALLOC);
+		goto exit;
+	}
+
+	/* Determine the location of the physical command buffer. */
+	gcmmu->cmdbufphys = gcmmu->gcpage.physical;
+	gcmmu->cmdbuflog = gcmmu->gcpage.logical;
+	gcmmu->cmdbufsize = PAGE_SIZE - GCMMU_SAFE_ZONE_SIZE;
+
+	/* Determine the location of the safe zone. */
+	gcmmu->safezonephys = gcmmu->gcpage.physical + gcmmu->cmdbufsize;
+	gcmmu->safezonelog = (unsigned int *) ((unsigned char *)
+		gcmmu->gcpage.logical + gcmmu->cmdbufsize);
+	gcmmu->safezonesize = GCMMU_SAFE_ZONE_SIZE;
+
+	/* Reset the master table. */
+	gcmmu->master = ~0U;
+
+	/* Initialize the list of vacant arenas. */
+	INIT_LIST_HEAD(&gcmmu->vacarena);
+
+exit:
+	GCEXITARG(GCZONE_INIT, "gc%s = 0x%08X\n",
+		(gcerror == GCERR_NONE) ? "result" : "error", gcerror);
+	return gcerror;
+}
+
+void gcmmu_exit(struct gccorecontext *gccorecontext)
+{
+	struct gcmmu *gcmmu = &gccorecontext->gcmmu;
+	struct list_head *head;
+	struct gcmmuarena *arena;
+
+	GCENTER(GCZONE_INIT);
+
+	/* Free the safe zone. */
+	gc_free_noncached(&gcmmu->gcpage);
+
+	/* Free vacant arena list. */
+	while (!list_empty(&gcmmu->vacarena)) {
+		head = gcmmu->vacarena.next;
+		arena = list_entry(head, struct gcmmuarena, link);
+		list_del(head);
+		kfree(arena);
+	}
+
+	GCEXIT(GCZONE_INIT);
+}
+
+enum gcerror gcmmu_create_context(struct gccorecontext *gccorecontext,
+				  struct gcmmucontext *gcmmucontext,
+				  pid_t pid)
+{
+	enum gcerror gcerror;
+	struct gcmmu *gcmmu = &gccorecontext->gcmmu;
+	struct gcmmuarena *arena = NULL;
+	unsigned int *logical;
+	unsigned int i;
+
+	GCENTER(GCZONE_CONTEXT);
+
+	if (gcmmucontext == NULL) {
+		gcerror = GCERR_MMU_CTXT_BAD;
+		goto exit;
+	}
+
+	/* Reset the context. */
+	memset(gcmmucontext, 0, sizeof(struct gcmmucontext));
+
+	/* Initialize access lock. */
+	GCLOCK_INIT(&gcmmucontext->lock);
+
+	/* Initialize arena lists. */
+	INIT_LIST_HEAD(&gcmmucontext->vacant);
+	INIT_LIST_HEAD(&gcmmucontext->allocated);
+
+	/* Mark context as dirty. */
+	gcmmucontext->dirty = true;
+
+	/* Set PID. */
+	gcmmucontext->pid = pid;
+
+	/* Allocate MTLB table. */
+	gcerror = gc_alloc_cached(&gcmmucontext->master, GCMMU_MTLB_SIZE);
+	if (gcerror != GCERR_NONE) {
+		gcerror = GCERR_SETGRP(gcerror, GCERR_MMU_MTLB_ALLOC);
+		goto exit;
+	}
+
+	/* Invalidate MTLB entries. */
+	logical = gcmmucontext->master.logical;
+	for (i = 0; i < GCMMU_MTLB_ENTRY_NUM; i += 1)
+		logical[i] = GCMMU_MTLB_ENTRY_VACANT;
+
+	/* Set MMU table mode. */
+	gcmmucontext->mmuconfig.reg.master_mask
+		= GCREG_MMU_CONFIGURATION_MASK_MODE_ENABLED;
+	gcmmucontext->mmuconfig.reg.master = GCMMU_MTLB_MODE;
+
+	/* Set the table address. */
+	gcmmucontext->mmuconfig.reg.address_mask
+		= GCREG_MMU_CONFIGURATION_MASK_ADDRESS_ENABLED;
+	gcmmucontext->mmuconfig.reg.address
+		= GCGETFIELD(gcmmucontext->master.physical,
+			     GCREG_MMU_CONFIGURATION, ADDRESS);
+
+	/* Allocate the first vacant arena. */
+	gcerror = get_arena(gcmmu, &arena);
+	if (gcerror != GCERR_NONE)
+		goto exit;
+
+	/* Entire range is currently vacant. */
+	arena->start.absolute = 0;
+	arena->end.absolute =
+	arena->count = GCMMU_MTLB_ENTRY_NUM * GCMMU_STLB_ENTRY_NUM;
+	list_add(&arena->link, &gcmmucontext->vacant);
+	GCDUMPARENA(GCZONE_ARENA, "initial vacant arena", arena);
+
+	/* Map the command queue. */
+	gcerror = gcqueue_map(gccorecontext, gcmmucontext);
+	if (gcerror != GCERR_NONE)
+		goto exit;
+
+	/* Reference MMU. */
+	gcmmu->refcount += 1;
+
+	GCEXIT(GCZONE_CONTEXT);
+	return GCERR_NONE;
+
+exit:
+	gcmmu_destroy_context(gccorecontext, gcmmucontext);
+
+	GCEXITARG(GCZONE_CONTEXT, "gcerror = 0x%08X\n", gcerror);
+	return gcerror;
+}
+
+enum gcerror gcmmu_destroy_context(struct gccorecontext *gccorecontext,
+				   struct gcmmucontext *gcmmucontext)
+{
+	enum gcerror gcerror;
+	struct gcmmu *gcmmu = &gccorecontext->gcmmu;
+	struct list_head *head;
+	struct gcmmuarena *arena;
+	struct gcmmustlbblock *nextblock;
+
+	GCENTER(GCZONE_CONTEXT);
+
+	if (gcmmucontext == NULL) {
+		gcerror = GCERR_MMU_CTXT_BAD;
+		goto exit;
+	}
+
+	/* Unmap the command queue. */
+	gcerror = gcqueue_unmap(gccorecontext, gcmmucontext);
+	if (gcerror != GCERR_NONE)
+		goto exit;
+
+	/* Free allocated arenas. */
+	while (!list_empty(&gcmmucontext->allocated)) {
+		head = gcmmucontext->allocated.next;
+		arena = list_entry(head, struct gcmmuarena, link);
+		release_physical_pages(arena);
+		list_move(head, &gcmmucontext->vacant);
+	}
+
+	/* Free slave tables. */
+	while (gcmmucontext->slavealloc != NULL) {
+		gc_free_cached(&gcmmucontext->slavealloc->pages);
+		nextblock = gcmmucontext->slavealloc->next;
+		kfree(gcmmucontext->slavealloc);
+		gcmmucontext->slavealloc = nextblock;
+	}
+
+	/* Free the master table. */
+	gc_free_cached(&gcmmucontext->master);
+
+	/* Free arenas. */
+	GCLOCK(&gcmmu->lock);
+	list_splice_init(&gcmmucontext->vacant, &gcmmu->vacarena);
+	GCUNLOCK(&gcmmu->lock);
+
+	/* Dereference. */
+	gcmmu->refcount -= 1;
+
+	GCEXIT(GCZONE_CONTEXT);
+	return GCERR_NONE;
+
+exit:
+	GCEXITARG(GCZONE_CONTEXT, "gcerror = 0x%08X\n", gcerror);
+	return gcerror;
+}
+
+enum gcerror gcmmu_enable(struct gccorecontext *gccorecontext,
+			  struct gcqueue *gcqueue)
+{
+	enum gcerror gcerror;
+	struct gcmmu *gcmmu = &gccorecontext->gcmmu;
+	struct list_head *head;
+	struct gccmdbuf *headcmdbuf;
+	struct gccmdbuf *gccmdbuf = NULL;
+	struct gcevent *gcevent = NULL;
+	struct gcmommuinit *gcmommuinit;
+	struct gcmosignal *gcmosignal;
+	struct gccmdend *gccmdend;
+	unsigned int status, enabled;
+
+	GCENTER(GCZONE_INIT);
+
+	/* Read the MMU status. */
+	status = gc_read_reg(GCREG_MMU_CONTROL_Address);
+	enabled = GCGETFIELD(status, GCREG_MMU_CONTROL, ENABLE);
+
+	/* Is MMU enabled? */
+	if (!enabled) {
+		GCDBG(GCZONE_MASTER, "enabling MMU.\n");
+
+		/* Queue cannot be empty. */
+		if (list_empty(&gcqueue->queue)) {
+			GCERR("queue is empty.");
+			gcerror = GCERR_MMU_INIT;
+			goto fail;
+		}
+
+		/* Get the first entry from the active queue. */
+		head = gcqueue->queue.next;
+		headcmdbuf = list_entry(head, struct gccmdbuf, link);
+
+		/* Allocate command init buffer. */
+		gcerror = gcqueue_alloc_cmdbuf(gcqueue, &gccmdbuf);
+		if (gcerror != GCERR_NONE)
+			goto fail;
+
+		/* Add event for the current command buffer. */
+		gcerror = gcqueue_alloc_event(gcqueue, &gcevent);
+		if (gcerror != GCERR_NONE)
+			goto fail;
+
+		/* Get free interrupt. */
+		gcerror = gcqueue_alloc_int(gcqueue, &gccmdbuf->interrupt);
+		if (gcerror != GCERR_NONE)
+			goto fail;
+
+		/* Initialize the event and add to the list. */
+		gcevent->handler = event_enable_mmu;
+
+		/* Attach records. */
+		list_add_tail(&gcevent->link, &gccmdbuf->events);
+		list_add(&gccmdbuf->link, &gcqueue->queue);
+
+		/* Program the safe zone and the master table address. */
+		gcmommuinit = (struct gcmommuinit *) gcmmu->cmdbuflog;
+		gcmommuinit->safe_ldst = gcmommuinit_safe_ldst;
+		gcmommuinit->safe = gcmmu->safezonephys;
+		gcmommuinit->mtlb = headcmdbuf->gcmmucontext->mmuconfig.raw;
+
+		/* Update the cached master */
+		gcmmu->master = gcmommuinit->mtlb;
+
+		/* Configure EVENT command. */
+		gcmosignal = (struct gcmosignal *) (gcmommuinit + 1);
+		gcmosignal->signal_ldst = gcmosignal_signal_ldst;
+		gcmosignal->signal.raw = 0;
+		gcmosignal->signal.reg.id = gccmdbuf->interrupt;
+		gcmosignal->signal.reg.pe = GCREG_EVENT_PE_SRC_ENABLE;
+
+		/* Configure the END command. */
+		gccmdend = (struct gccmdend *) (gcmosignal + 1);
+		gccmdend->cmd.raw = gccmdend_const.cmd.raw;
+
+		/* Initialize the command buffer. */
+		gccmdbuf->gcmmucontext = headcmdbuf->gcmmucontext;
+		gccmdbuf->logical = (unsigned char *) gcmmu->cmdbuflog;
+		gccmdbuf->physical = gcmmu->cmdbufphys;
+		gccmdbuf->size = sizeof(struct gcmommuinit)
+			       + sizeof(struct gcmosignal)
+			       + sizeof(struct gccmdend);
+		gccmdbuf->count = (gccmdbuf->size + 7) >> 3;
+		gccmdbuf->gcmoterminator = NULL;
+
+		GCDUMPBUFFER(GCZONE_INIT, gccmdbuf->logical,
+				gccmdbuf->physical, gccmdbuf->size);
+	}
+
+	GCEXIT(GCZONE_INIT);
+	return GCERR_NONE;
+
+fail:
+	if (gcevent != NULL)
+		gcqueue_free_event(gcqueue, gcevent);
+
+	if (gccmdbuf != NULL)
+		gcqueue_free_cmdbuf(gcqueue, gccmdbuf, NULL);
+
+	GCEXITARG(GCZONE_CONTEXT, "gcerror = 0x%08X\n", gcerror);
+	return gcerror;
+}
+
+enum gcerror gcmmu_set_master(struct gccorecontext *gccorecontext,
+			      struct gcmmucontext *gcmmucontext)
+{
+	enum gcerror gcerror;
+	struct gcmmu *gcmmu = &gccorecontext->gcmmu;
+	struct gcmommumaster *gcmommumaster;
+
+	GCENTER(GCZONE_MASTER);
+
+	if (gcmmucontext == NULL) {
+		gcerror = GCERR_MMU_CTXT_BAD;
+		goto exit;
+	}
+
+	/* Did the master change? */
+	if (gcmmu->master == gcmmucontext->mmuconfig.raw) {
+		gcerror = GCERR_NONE;
+		goto exit;
+	}
+
+	/* Flush required when switching mmu contexts */
+	gcmmucontext->dirty = true;
+
+	/* Allocate command buffer space. */
+	gcerror = gcqueue_alloc(gccorecontext, gcmmucontext,
+				sizeof(struct gcmommumaster),
+				(void **) &gcmommumaster, NULL);
+	if (gcerror != GCERR_NONE) {
+		gcerror = GCERR_SETGRP(gcerror, GCERR_MMU_MTLB_SET);
+		goto exit;
+	}
+
+	/* Program master table address. */
+	gcmommumaster->master_ldst = gcmommumaster_master_ldst;
+	gcmommumaster->master = gcmmucontext->mmuconfig.raw;
+
+	/* Update master table address. */
+	gcmmu->master = gcmmucontext->mmuconfig.raw;
+
+exit:
+	GCEXITARG(GCZONE_MASTER, "gc%s = 0x%08X\n",
+		(gcerror == GCERR_NONE) ? "result" : "error", gcerror);
+	return gcerror;
+}
+
+enum gcerror gcmmu_map(struct gccorecontext *gccorecontext,
+		       struct gcmmucontext *gcmmucontext,
+		       struct gcmmuphysmem *mem,
+		       struct gcmmuarena **mapped)
+{
+	enum gcerror gcerror = GCERR_NONE;
+	bool locked = false;
+	struct gcmmu *gcmmu = &gccorecontext->gcmmu;
+	struct list_head *arenahead;
+	struct gcmmuarena *vacant = NULL, *split;
+	struct gcmmustlb *slave;
+	unsigned int *stlblogical;
+	union gcmmuloc index;
+	unsigned int i, allocated, count;
+	pte_t *parray_alloc = NULL;
+	pte_t *parray;
+
+	GCENTER(GCZONE_MAPPING);
+
+	if (gcmmucontext == NULL) {
+		gcerror = GCERR_MMU_CTXT_BAD;
+		goto exit;
+	}
+
+	if ((mem == NULL) || (mem->count <= 0) || (mapped == NULL) ||
+		((mem->pagesize != 0) && (mem->pagesize != GCMMU_PAGE_SIZE))) {
+		gcerror = GCERR_MMU_ARG;
+		goto exit;
+	}
+
+	GCLOCK(&gcmmucontext->lock);
+	locked = true;
+
+	/*
+	 * Find available sufficient arena.
+	 */
+
+	GCDBG(GCZONE_MAPPING, "mapping (%d) pages\n", mem->count);
+
+	list_for_each(arenahead, &gcmmucontext->vacant) {
+		vacant = list_entry(arenahead, struct gcmmuarena, link);
+		if (vacant->count >= mem->count)
+			break;
+	}
+
+	if (arenahead == &gcmmucontext->vacant) {
+		gcerror = GCERR_MMU_OOM;
+		goto exit;
+	}
+
+	GCDUMPARENA(GCZONE_ARENA, "allocating from arena", vacant);
+
+	/*
+	 * If page array isn't provided, create it here.
+	 */
+
+	/* Reset page array. */
+	vacant->pages = NULL;
+
+	/* No page array given? */
+	if (mem->pages == NULL) {
+		/* Allocate physical address array. */
+		parray_alloc = kmalloc(mem->count * sizeof(pte_t *),
+					GFP_KERNEL);
+		if (parray_alloc == NULL) {
+			GCERR("failed to allocate page address array\n");
+			gcerror = GCERR_SETGRP(GCERR_OODM,
+						GCERR_MMU_PHYS_ALLOC);
+			goto exit;
+		}
+
+		/* Fetch page addresses. */
+		gcerror = get_physical_pages(mem, parray_alloc, vacant);
+		if (gcerror != GCERR_NONE)
+			goto exit;
+
+		parray = parray_alloc;
+
+		GCDBG(GCZONE_MAPPING,
+			"physical page array allocated (0x%08X)\n",
+			(unsigned int) parray);
+	} else {
+		parray = mem->pages;
+
+		GCDBG(GCZONE_MAPPING,
+			"physical page array provided (0x%08X)\n",
+			(unsigned int) parray);
+	}
+
+	/*
+	 * Create the mapping.
+	 */
+
+	index.absolute = vacant->start.absolute;
+	slave = &gcmmucontext->slave[index.loc.mtlb];
+	count = mem->count;
+
+	while (count > 0) {
+		/* Allocate slaves if not yet allocated. */
+		if (slave->logical == NULL) {
+			gcerror = allocate_slave(gcmmucontext, index);
+			if (gcerror != GCERR_NONE)
+				goto exit;
+		}
+
+		/* Determine the number of entries allocated. */
+		allocated = GCMMU_STLB_ENTRY_NUM - index.loc.stlb;
+		if (allocated > count)
+			allocated = count;
+
+		/* Initialize slave entries. */
+		stlblogical = &slave->logical[index.loc.stlb];
+		for (i = 0; i < allocated; i += 1)
+			*stlblogical++
+				= (*parray++ & GCMMU_STLB_ADDRESS_MASK)
+				| GCMMU_STLB_PRESENT
+				| GCMMU_STLB_EXCEPTION
+				| GCMMU_STLB_WRITEABLE;
+
+		/* Flush CPU cache. */
+		gc_flush_region(slave->physical, slave->logical,
+				index.loc.stlb * sizeof(unsigned int),
+				allocated * sizeof(unsigned int));
+
+		GCDBG(GCZONE_MAPPING, "allocated %d pages at %d.%d\n",
+		      allocated, index.loc.mtlb, index.loc.stlb);
+
+		/* Advance. */
+		slave += 1;
+		index.absolute += allocated;
+		count -= allocated;
+	}
+
+	/*
+	 * Claim arena.
+	 */
+
+	/* Split the arena. */
+	if (vacant->count != mem->count) {
+		GCDBG(GCZONE_MAPPING, "splitting vacant arena\n");
+
+		gcerror = get_arena(gcmmu, &split);
+		if (gcerror != GCERR_NONE)
+			goto exit;
+
+		split->start.absolute = index.absolute;
+		split->end.absolute = vacant->end.absolute;
+		split->count = vacant->count - mem->count;
+		list_add(&split->link, &vacant->link);
+
+		vacant->end.absolute = index.absolute;
+		vacant->count = mem->count;
+	}
+
+	GCDUMPARENA(GCZONE_ARENA, "allocated arena", vacant);
+
+	/* Move the vacant arena to the list of allocated arenas. */
+	list_move(&vacant->link, &gcmmucontext->allocated);
+
+	/* Set page size. */
+	mem->pagesize = GCMMU_PAGE_SIZE;
+
+	/* Determine the virtual address. */
+	vacant->address
+		= ((vacant->start.loc.mtlb << GCMMU_MTLB_SHIFT)
+					    & GCMMU_MTLB_MASK)
+		| ((vacant->start.loc.stlb << GCMMU_STLB_SHIFT)
+					    & GCMMU_STLB_MASK)
+		| (mem->offset & GCMMU_OFFSET_MASK);
+
+	/* Determine the size of the area. */
+	vacant->size = mem->count * GCMMU_PAGE_SIZE - mem->offset;
+
+	/* Invalidate the MMU. */
+	gcmmucontext->dirty = true;
+
+	/* Set the result. */
+	*mapped = vacant;
+
+	GCDBG(GCZONE_MAPPING, "mapped %d bytes at 0x%08X\n",
+		vacant->size, vacant->address);
+
+	/* Dump tables. */
+	GCDUMPMMU(GCZONE_DUMPMAP, gcmmucontext);
+
+exit:
+	if (parray_alloc != NULL) {
+		kfree(parray_alloc);
+
+		if (gcerror != GCERR_NONE)
+			release_physical_pages(vacant);
+	}
+
+	if (locked)
+		GCUNLOCK(&gcmmucontext->lock);
+
+	GCEXITARG(GCZONE_MAPPING, "gc%s = 0x%08X\n",
+		(gcerror == GCERR_NONE) ? "result" : "error", gcerror);
+	return gcerror;
+}
+
+enum gcerror gcmmu_unmap(struct gccorecontext *gccorecontext,
+			 struct gcmmucontext *gcmmucontext,
+			 struct gcmmuarena *mapped)
+{
+	enum gcerror gcerror = GCERR_NONE;
+	bool locked = false;
+	struct gcmmu *gcmmu = &gccorecontext->gcmmu;
+	struct list_head *allochead, *prevhead, *nexthead;
+	struct gcmmuarena *allocated, *prevvacant, *nextvacant = NULL;
+	struct gcmmustlb *slave;
+	unsigned int *stlblogical;
+	union gcmmuloc index;
+	unsigned int i, freed, count;
+
+	GCENTER(GCZONE_MAPPING);
+
+	if (gcmmucontext == NULL) {
+		gcerror = GCERR_MMU_CTXT_BAD;
+		goto exit;
+	}
+
+	GCLOCK(&gcmmucontext->lock);
+	locked = true;
+
+	/*
+	 * Find the arena.
+	 */
+
+	GCDBG(GCZONE_MAPPING, "unmapping arena 0x%08X\n",
+		(unsigned int) mapped);
+
+	list_for_each(allochead, &gcmmucontext->allocated) {
+		allocated = list_entry(allochead, struct gcmmuarena, link);
+		if (allocated == mapped)
+			break;
+	}
+
+	if (allochead == &gcmmucontext->allocated) {
+		GCERR("mapped arena 0x%08X not found.\n",
+			(unsigned int) mapped);
+		gcerror = GCERR_MMU_ARG;
+		goto exit;
+	}
+
+	GCDBG(GCZONE_MAPPING, "mapped arena found:\n");
+	GCDBG(GCZONE_MAPPING, "  arena phys = 0x%08X\n", allocated->address);
+	GCDBG(GCZONE_MAPPING, "  arena size = %d\n", allocated->size);
+
+	/*
+	 * Free slave tables.
+	 */
+
+	index.absolute = allocated->start.absolute;
+	slave = &gcmmucontext->slave[index.loc.mtlb];
+	count = allocated->count;
+
+	while (count > 0) {
+		/* Determine the number of entries freed. */
+		freed = GCMMU_STLB_ENTRY_NUM - index.loc.stlb;
+		if (freed > count)
+			freed = count;
+
+		GCDBG(GCZONE_MAPPING, "freeing %d pages at %d.%d\n",
+			freed, index.loc.mtlb, index.loc.stlb);
+
+		/* Free slave entries. */
+		stlblogical = &slave->logical[index.loc.stlb];
+		for (i = 0; i < freed; i += 1)
+			*stlblogical++ = GCMMU_STLB_ENTRY_VACANT;
+
+		/* Flush CPU cache. */
+		gc_flush_region(slave->physical, slave->logical,
+				index.loc.stlb * sizeof(unsigned int),
+				freed * sizeof(unsigned int));
+
+		/* Advance. */
+		slave += 1;
+		index.absolute += freed;
+		count -= freed;
+	}
+
+	/*
+	 * Delete page cache for the arena.
+	 */
+
+	release_physical_pages(allocated);
+
+	/*
+	 * Find point of insertion and free the arena.
+	 */
+
+	GCDBG(GCZONE_MAPPING,
+		"looking for the point of insertion.\n");
+
+	list_for_each(nexthead, &gcmmucontext->vacant) {
+		nextvacant = list_entry(nexthead, struct gcmmuarena, link);
+		if (nextvacant->start.absolute >= allocated->end.absolute) {
+			GCDBG(GCZONE_MAPPING, "  point of insertion found.\n");
+			break;
+		}
+	}
+
+	/* Get the previous vacant entry. */
+	prevhead = nexthead->prev;
+
+	/* Merge the area back into vacant list. */
+	if (siblings(&gcmmucontext->vacant, prevhead, allochead)) {
+		if (siblings(&gcmmucontext->vacant, allochead, nexthead)) {
+			prevvacant = list_entry(prevhead, struct gcmmuarena,
+						link);
+
+			GCDBG(GCZONE_MAPPING, "merging three arenas:\n");
+
+			GCDUMPARENA(GCZONE_ARENA, "previous arena", prevvacant);
+			GCDUMPARENA(GCZONE_ARENA, "allocated arena", allocated);
+			GCDUMPARENA(GCZONE_ARENA, "next arena", nextvacant);
+
+			/* Merge all three arenas. */
+			prevvacant->count += allocated->count;
+			prevvacant->count += nextvacant->count;
+			prevvacant->end.absolute = nextvacant->end.absolute;
+
+			/* Free the merged arenas. */
+			GCLOCK(&gcmmu->lock);
+			list_move(allochead, &gcmmu->vacarena);
+			list_move(nexthead, &gcmmu->vacarena);
+			GCUNLOCK(&gcmmu->lock);
+		} else {
+			prevvacant = list_entry(prevhead, struct gcmmuarena,
+						link);
+
+			GCDBG(GCZONE_MAPPING, "merging with the previous:\n");
+
+			GCDUMPARENA(GCZONE_ARENA, "previous arena", prevvacant);
+			GCDUMPARENA(GCZONE_ARENA, "allocated arena", allocated);
+
+			/* Merge with the previous. */
+			prevvacant->count += allocated->count;
+			prevvacant->end.absolute = allocated->end.absolute;
+
+			/* Free the merged arena. */
+			GCLOCK(&gcmmu->lock);
+			list_move(allochead, &gcmmu->vacarena);
+			GCUNLOCK(&gcmmu->lock);
+		}
+	} else if (siblings(&gcmmucontext->vacant, allochead, nexthead)) {
+		GCDBG(GCZONE_MAPPING, "merged with the next:\n");
+
+		GCDUMPARENA(GCZONE_ARENA, "allocated arena", allocated);
+		GCDUMPARENA(GCZONE_ARENA, "next arena", nextvacant);
+
+		/* Merge with the next arena. */
+		nextvacant->start.absolute = allocated->start.absolute;
+		nextvacant->count += allocated->count;
+
+		/* Free the merged arena. */
+		GCLOCK(&gcmmu->lock);
+		list_move(allochead, &gcmmu->vacarena);
+		GCUNLOCK(&gcmmu->lock);
+	} else {
+		GCDBG(GCZONE_MAPPING,
+		      "nothing to merge with, inserting in between:\n");
+		GCDUMPARENA(GCZONE_ARENA, "allocated arena", allocated);
+
+		/* Neighbor vacant arenas are not siblings, can't merge. */
+		list_move(allochead, prevhead);
+	}
+
+	/* Invalidate the MMU. */
+	gcmmucontext->dirty = true;
+
+	/* Dump tables. */
+	GCDUMPMMU(GCZONE_DUMPUNMAP, gcmmucontext);
+
+exit:
+	if (locked)
+		GCUNLOCK(&gcmmucontext->lock);
+
+	GCEXITARG(GCZONE_MAPPING, "gc%s = 0x%08X\n",
+		(gcerror == GCERR_NONE) ? "result" : "error", gcerror);
+	return gcerror;
+}
+
+enum gcerror gcmmu_flush(struct gccorecontext *gccorecontext,
+			 struct gcmmucontext *gcmmucontext)
+{
+	enum gcerror gcerror = GCERR_NONE;
+	struct gcmommuflush *flushlogical;
+	unsigned int flushaddress;
+	struct gcqueue *gcqueue;
+
+	GCENTER(GCZONE_FLUSH);
+
+	GCLOCK(&gcmmucontext->lock);
+
+	if (gcmmucontext->dirty) {
+		/* Allocate space for the flush. */
+		gcerror = gcqueue_alloc(gccorecontext, gcmmucontext,
+					sizeof(struct gcmommuflush),
+					(void **) &flushlogical, &flushaddress);
+		if (gcerror != GCERR_NONE)
+			goto exit;
+
+		/* Get a shortcut to the queue object. */
+		gcqueue = &gccorecontext->gcqueue;
+
+		/* Store flush information. */
+		gcqueue->flushlogical = flushlogical;
+		gcqueue->flushaddress = flushaddress;
+
+		/* Validate the context. */
+		gcmmucontext->dirty = false;
+	}
+
+exit:
+	GCUNLOCK(&gcmmucontext->lock);
+
+	GCEXITARG(GCZONE_FLUSH, "gc%s = 0x%08X\n",
+		(gcerror == GCERR_NONE) ? "result" : "error", gcerror);
+	return gcerror;
+}
+
+void gcmmu_flush_finalize(struct gccmdbuf *gccmdbuf,
+			  struct gcmommuflush *flushlogical,
+			  unsigned int flushaddress)
+{
+	int size;
+	unsigned int datacount;
+
+	GCENTER(GCZONE_FLUSH);
+
+	/* Compute the size of the command buffer after the flush block */
+	size = gccmdbuf->physical + gccmdbuf->size
+		- flushaddress - sizeof(struct gcmommuflush);
+
+	/* Compute the data count. */
+	datacount = (size + 7) >> 3;
+
+	/* Flush 2D PE cache. */
+	flushlogical->peflush.flush_ldst = gcmoflush_flush_ldst;
+	flushlogical->peflush.flush.reg = gcregflush_pe2D;
+
+	/* Arm the FE-PE semaphore. */
+	flushlogical->peflushsema.sema_ldst = gcmosema_sema_ldst;
+	flushlogical->peflushsema.sema.reg  = gcregsema_fe_pe;
+
+	/* Stall FE until PE is done flushing. */
+	flushlogical->peflushstall.cmd.fld = gcfldstall;
+	flushlogical->peflushstall.arg.fld = gcfldstall_fe_pe;
+
+	/* LINK to the next slot to flush FE FIFO. */
+	flushlogical->feflush.cmd.fld = gcfldlink4;
+	flushlogical->feflush.address
+		= flushaddress
+		+ offsetof(struct gcmommuflush, mmuflush_ldst);
+
+	/* Flush MMU cache. */
+	flushlogical->mmuflush_ldst = gcmommuflush_mmuflush_ldst;
+	flushlogical->mmuflush.reg = gcregmmu_flush;
+
+	/* Arm the FE-PE semaphore. */
+	flushlogical->mmuflushsema.sema_ldst = gcmosema_sema_ldst;
+	flushlogical->mmuflushsema.sema.reg  = gcregsema_fe_pe;
+
+	/* Stall FE until PE is done flushing. */
+	flushlogical->mmuflushstall.cmd.fld = gcfldstall;
+	flushlogical->mmuflushstall.arg.fld = gcfldstall_fe_pe;
+
+	/* LINK to the next slot to flush FE FIFO. */
+	flushlogical->link.cmd.fld.opcode = GCREG_COMMAND_OPCODE_LINK;
+	flushlogical->link.cmd.fld.count = datacount;
+	flushlogical->link.address = flushaddress + sizeof(struct gcmommuflush);
+
+	GCEXIT(GCZONE_FLUSH);
+}
+
+enum gcerror gcmmu_fixup(struct list_head *fixuplist,
+			 unsigned int *data)
+{
+	enum gcerror gcerror = GCERR_NONE;
+	struct list_head *head;
+	struct gcfixup *gcfixup;
+	struct gcfixupentry *table;
+	struct gcmmuarena *arena;
+	unsigned int dataoffset;
+	unsigned int i;
+
+	GCENTER(GCZONE_FIXUP);
+
+	/* Process fixups. */
+	list_for_each(head, fixuplist) {
+		gcfixup = list_entry(head, struct gcfixup, link);
+
+		GCDBG(GCZONE_FIXUP, "%d fixup(s) @ 0x%08X\n",
+			gcfixup->count, (unsigned int) gcfixup);
+
+		/* Apply fixups. */
+		table = gcfixup->fixup;
+		for (i = 0; i < gcfixup->count; i += 1) {
+			GCDBG(GCZONE_FIXUP, "#%d\n", i);
+			GCDBG(GCZONE_FIXUP, "  buffer offset = 0x%08X\n",
+				table->dataoffset * 4);
+			GCDBG(GCZONE_FIXUP, "  surface offset = 0x%08X\n",
+				table->surfoffset);
+
+			dataoffset = table->dataoffset;
+
+			arena = (struct gcmmuarena *) data[dataoffset];
+			if (!virt_addr_valid(arena)) {
+				GCERR("bad arena @ 0x%08X\n",
+				      (unsigned int) arena);
+				gcerror = GCERR_OODM;
+				goto exit;
+			}
+
+			GCDBG(GCZONE_FIXUP, "  arena = 0x%08X\n",
+				(unsigned int) arena);
+			GCDBG(GCZONE_FIXUP, "  arena phys = 0x%08X\n",
+				arena->address);
+			GCDBG(GCZONE_FIXUP, "  arena size = %d\n",
+				arena->size);
+
+			data[dataoffset] = arena->address + table->surfoffset;
+
+			GCDBG(GCZONE_FIXUP, "  surface @ 0x%08X\n",
+				data[dataoffset]);
+
+			table += 1;
+		}
+	}
+
+exit:
+	GCEXITARG(GCZONE_FIXUP, "gc%s = 0x%08X\n",
+		(gcerror == GCERR_NONE) ? "result" : "error", gcerror);
+	return gcerror;
+}
diff --git a/drivers/misc/gcx/gccore/gcmmu.h b/drivers/misc/gcx/gccore/gcmmu.h
new file mode 100644
index 0000000..445f7fd
--- /dev/null
+++ b/drivers/misc/gcx/gccore/gcmmu.h
@@ -0,0 +1,271 @@
+/*
+ * gcmmu.h
+ *
+ * Copyright (C) 2010-2011 Vivante Corporation.
+ *
+ * This package is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#ifndef GCMMU_H
+#define GCMMU_H
+
+#include <linux/gccore.h>
+#include "gcmem.h"
+#include "gcqueue.h"
+
+/*******************************************************************************
+ * Master table can be configured in 1KB mode with 256 maximum entries
+ * or 4KB mode with 1024 maximum entries.
+ *
+ * Address bit allocation.
+ * +------+------+--------+
+ * | MTLB | STLB | Offset |
+ * +------+------+--------+
+ *
+ * # of address bits | # of address bits | Page | Addressable | Total
+ *          /        |          /        | size |  per one    | addressable
+ * # of MTLB entries | # of STLB entries |      | MTLB entry  |
+ * ------------------+-------------------+------+-------------+------------
+ *       8 / 256     |      4 / 16       |  1MB |             |
+ *                   |      8 / 256      | 64KB |     16MB    |    4GB
+ *                   |     12 / 4096     |  4KB |             |
+ * ------------------+-------------------+------+-------------+------------
+ *      10 / 1024    |      6 / 64       | 64KB |             |
+ *                   |     10 / 1024     |  4KB |      4MB    |    4GB
+ */
+
+/* Page size. */
+#define GCMMU_PAGE_SIZE			4096
+
+/* Master table definitions. */
+#define GCMMU_MTLB_BITS			8
+#define GCMMU_MTLB_ENTRY_NUM		(1 << GCMMU_MTLB_BITS)
+#define GCMMU_MTLB_SIZE			(GCMMU_MTLB_ENTRY_NUM << 2)
+#define GCMMU_MTLB_SHIFT		(32 - GCMMU_MTLB_BITS)
+#define GCMMU_MTLB_MASK			(((1U << GCMMU_MTLB_BITS) - 1) \
+						<< GCMMU_MTLB_SHIFT)
+
+#if GCMMU_MTLB_BITS == 8
+#	define GCMMU_MTLB_MODE		GCREG_MMU_CONFIGURATION_MODE_MODE1_K
+#elif GCMMU_MTLB_BITS == 10
+#	define GCMMU_MTLB_MODE		GCREG_MMU_CONFIGURATION_MODE_MODE4_K
+#else
+#	error Invalid GCMMU_MTLB_BITS.
+#endif
+
+#define GCMMU_MTLB_PRESENT_MASK		0x00000001
+#define GCMMU_MTLB_EXCEPTION_MASK	0x00000002
+#define GCMMU_MTLB_PAGE_SIZE_MASK	0x0000000C
+#define GCMMU_MTLB_SLAVE_MASK		0xFFFFFFC0
+
+#define GCMMU_MTLB_PRESENT		0x00000001
+#define GCMMU_MTLB_EXCEPTION		0x00000002
+#define GCMMU_MTLB_4K_PAGE		0x00000000
+
+#define GCMMU_MTLB_ENTRY_VACANT		GCMMU_MTLB_EXCEPTION
+
+/* Slave table definitions. */
+#define GCMMU_STLB_BITS			12
+#define GCMMU_STLB_ENTRY_NUM		(1 << GCMMU_STLB_BITS)
+#define GCMMU_STLB_SIZE			(GCMMU_STLB_ENTRY_NUM << 2)
+#define GCMMU_STLB_SHIFT		(32 - (GCMMU_MTLB_BITS \
+						+ GCMMU_STLB_BITS))
+#define GCMMU_STLB_MASK			(((1U << GCMMU_STLB_BITS) - 1) \
+						<< GCMMU_STLB_SHIFT)
+
+#define GCMMU_STLB_PRESENT_MASK		0x00000001
+#define GCMMU_STLB_EXCEPTION_MASK	0x00000002
+#define GCMMU_STLB_WRITEABLE_MASK	0x00000004
+#define GCMMU_STLB_ADDRESS_MASK		0xFFFFF000
+
+#define GCMMU_STLB_PRESENT		0x00000001
+#define GCMMU_STLB_EXCEPTION		0x00000002
+#define GCMMU_STLB_WRITEABLE		0x00000004
+
+#define GCMMU_STLB_ENTRY_VACANT		GCMMU_STLB_EXCEPTION
+
+/* Page offset definitions. */
+#define GCMMU_OFFSET_BITS		(32 - GCMMU_MTLB_BITS - GCMMU_STLB_BITS)
+#define GCMMU_OFFSET_MASK		((1U << GCMMU_OFFSET_BITS) - 1)
+
+#define GCMMU_SAFE_ZONE_SIZE		64
+
+/* STLB preallocation count. This value controls how many slave tables will be
+ * allocated every time we run out of available slave tables during mapping.
+ * The value must be between 1 and the total number of slave tables possible,
+ * which is equal to 256 assuming 4KB page size. */
+#define GCMMU_STLB_PREALLOC_COUNT	(GCMMU_MTLB_ENTRY_NUM / 4)
+
+
+/*******************************************************************************
+ * MMU structures.
+ */
+
+/* This union defines a location within MMU. */
+union gcmmuloc {
+	struct _loc {
+		unsigned int stlb:GCMMU_STLB_BITS;
+		unsigned int mtlb:GCMMU_MTLB_BITS;
+	} loc;
+
+	unsigned int absolute;
+};
+
+/* Arenas describe memory regions. Two lists of areanas are maintained:
+ * one that defines a list of vacant arenas ready to map and the other
+ * a list of already mapped arenas. */
+struct gcmmuarena {
+	/* Arena starting and ending points. */
+	union gcmmuloc start;
+	union gcmmuloc end;
+
+	/* Number of pages. */
+	unsigned int count;
+
+	/* Mapped virtual pointer. */
+	unsigned int address;
+
+	/* Client's virtual pointer. */
+	void *logical;
+
+	/* Size of the mapped buffer. */
+	unsigned int size;
+
+	/* Page descriptor array. */
+	struct page **pages;
+
+	/* Prev/next arena. */
+	struct list_head link;
+};
+
+/* MMU shared object. */
+struct gcmmu {
+	/* Access lock. */
+	GCLOCK_TYPE lock;
+
+	/* Reference count. */
+	int refcount;
+
+	/* One physical page used for MMU management. */
+	struct gcpage gcpage;
+
+	/* Physical command buffer. */
+	unsigned int cmdbufphys;
+	unsigned int *cmdbuflog;
+	unsigned int cmdbufsize;
+
+	/* Safe zone location. */
+	unsigned int safezonephys;
+	unsigned int *safezonelog;
+	unsigned int safezonesize;
+
+	/* Currently set master table. */
+	unsigned int master;
+
+	/* Available page allocation arenas. */
+	struct list_head vacarena;
+};
+
+/* Slave table descriptor. */
+struct gcmmustlb {
+	unsigned int physical;
+	unsigned int *logical;
+};
+
+struct gcmmustlbblock;
+struct gcmmucontext {
+	/* Access lock. */
+	GCLOCK_TYPE lock;
+
+	/* PID of the owner process. */
+	pid_t pid;
+
+	/* If marked as dirty, MMU cache needs to be flushed. */
+	bool dirty;
+
+	/* Master table allocation. */
+	struct gcpage master;
+
+	/* Slave table descriptors. */
+	struct gcmmustlb slave[GCMMU_MTLB_ENTRY_NUM];
+	struct gcmmustlbblock *slavealloc;
+
+	/* MMU configuration. */
+	union mmuconfig {
+		struct gcregmmuconfiguration reg;
+		unsigned int raw;
+	} mmuconfig;
+
+	unsigned long physical;
+
+	/* Page mapping tracking. */
+	struct list_head vacant;
+	struct list_head allocated;
+
+	/* Driver instance has only one set of command buffers that must be
+	 * mapped the same exact way in all clients. This array stores
+	 * pointers to arena structures of mapped storage buffers. */
+	struct gcmmuarena *storagearray[GC_STORAGE_COUNT];
+
+	/* Prev/next context. */
+	struct list_head link;
+};
+
+
+/*******************************************************************************
+ * MMU management API.
+ */
+
+struct gcmmuphysmem {
+	/* Virtual pointer and offset of the first page to map. */
+	unsigned int base;
+	unsigned int offset;
+
+	/* An array of physical addresses of the pages to map. */
+	unsigned int count;
+	pte_t *pages;
+
+	/* 0 => system default. */
+	int pagesize;
+};
+
+struct gccorecontext;
+
+enum gcerror gcmmu_init(struct gccorecontext *gccorecontext);
+void gcmmu_exit(struct gccorecontext *gccorecontext);
+
+enum gcerror gcmmu_create_context(struct gccorecontext *gccorecontext,
+				  struct gcmmucontext *gcmmucontext,
+				  pid_t pid);
+enum gcerror gcmmu_destroy_context(struct gccorecontext *gccorecontext,
+				   struct gcmmucontext *gcmmucontext);
+
+enum gcerror gcmmu_enable(struct gccorecontext *gccorecontext,
+			  struct gcqueue *gcqueue);
+enum gcerror gcmmu_set_master(struct gccorecontext *gccorecontext,
+			      struct gcmmucontext *gcmmucontext);
+
+enum gcerror gcmmu_map(struct gccorecontext *gccorecontext,
+		       struct gcmmucontext *gcmmucontext,
+		       struct gcmmuphysmem *mem,
+		       struct gcmmuarena **mapped);
+enum gcerror gcmmu_unmap(struct gccorecontext *gccorecontext,
+			 struct gcmmucontext *gcmmucontext,
+			 struct gcmmuarena *mapped);
+
+enum gcerror gcmmu_flush(struct gccorecontext *gccorecontext,
+			 struct gcmmucontext *gcmmucontext);
+void gcmmu_flush_finalize(struct gccmdbuf *openentry,
+			  struct gcmommuflush *flushlogical,
+			  unsigned int flushaddress);
+
+enum gcerror gcmmu_fixup(struct list_head *fixuplist,
+			 unsigned int *data);
+
+#endif
diff --git a/drivers/misc/gcx/gccore/gcqueue.c b/drivers/misc/gcx/gccore/gcqueue.c
new file mode 100644
index 0000000..c5a1921
--- /dev/null
+++ b/drivers/misc/gcx/gccore/gcqueue.c
@@ -0,0 +1,1656 @@
+/*
+ * gcqueue.c
+ *
+ * Copyright (C) 2010-2011 Vivante Corporation.
+ *
+ * This package is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#include <linux/slab.h>
+#include <linux/kthread.h>
+#include <linux/interrupt.h>
+#include <asm/cacheflush.h>
+#include "gcmain.h"
+
+#define GCZONE_NONE		0
+#define GCZONE_ALL		(~0U)
+#define GCZONE_INIT		(1 << 0)
+#define GCZONE_ISR		(1 << 1)
+#define GCZONE_THREAD		(1 << 2)
+#define GCZONE_INTERRUPT	(1 << 3)
+#define GCZONE_BUFFER		(1 << 4)
+#define GCZONE_EVENT		(1 << 5)
+#define GCZONE_QUEUE		(1 << 6)
+#define GCZONE_MAPPING		(1 << 7)
+#define GCZONE_ALLOC		(1 << 8)
+#define GCZONE_EXEC		(1 << 9)
+
+GCDBG_FILTERDEF(queue, GCZONE_NONE,
+		"init",
+		"isr",
+		"thread",
+		"interrupt",
+		"buffer",
+		"event",
+		"queue",
+		"mapping",
+		"alloc",
+		"exec")
+
+#define GCDBG_QUEUE(zone, message, gccmdbuf) { \
+	GCDBG(zone, message "queue entry @ 0x%08X:\n", \
+	      (unsigned int) gccmdbuf); \
+	GCDBG(zone, "  logical = 0x%08X\n", \
+	      (unsigned int) gccmdbuf->logical); \
+	GCDBG(zone, "  physical = 0x%08X\n", \
+	      gccmdbuf->physical); \
+	GCDBG(zone, "  size = %d, count = %d\n", \
+	      gccmdbuf->size, gccmdbuf->count); \
+	GCDBG(zone, "  terminator = 0x%08X\n", \
+	      (unsigned int) gccmdbuf->gcmoterminator); \
+	GCDBG(zone, "  int = %d\n", \
+	      gccmdbuf->interrupt); \
+	GCDBG(zone, "  %s\n", \
+	      list_empty(&gccmdbuf->events) ? "no events" : "has events"); \
+}
+
+
+/*******************************************************************************
+ * Internal definitions.
+ */
+
+/* GPU timeout in milliseconds. The timeout value controls when the power
+ * on the GPU is pulled if there is no activity in progress or scheduled. */
+#define GC_THREAD_TIMEOUT	20
+
+/* Time in milliseconds to wait for GPU to become idle. */
+#define GC_IDLE_TIMEOUT		100
+
+/* The size of storage buffer. */
+#define GC_STORAGE_SIZE		((GC_BUFFER_SIZE * GC_CMDBUF_FACTOR + \
+					(PAGE_SIZE - 1)) & PAGE_MASK)
+
+/* Number of pages per one kernel storage buffer. */
+#define GC_STORAGE_PAGES	(GC_STORAGE_SIZE / PAGE_SIZE)
+
+/* Reserved number of bytes at the end of storage buffer. */
+#define GC_TAIL_RESERVE		sizeof(struct gcmoterminator)
+
+/* Minimum available space requirement. */
+#define GC_MIN_THRESHOLD	((int) (GC_TAIL_RESERVE + 200))
+
+/* Event assignment. */
+#define GC_SIG_BUS_ERROR	31
+#define GC_SIG_MMU_ERROR	30
+#define GC_SIG_DMA_DONE_BITS	30
+
+#define GC_SIG_MASK_BUS_ERROR	(1 << GC_SIG_BUS_ERROR)
+#define GC_SIG_MASK_MMU_ERROR	(1 << GC_SIG_MMU_ERROR)
+#define GC_SIG_MASK_DMA_DONE	((1 << GC_SIG_DMA_DONE_BITS) - 1)
+
+
+/*******************************************************************************
+ * ISR.
+ */
+
+static irqreturn_t gcisr(int irq, void *_gccorecontext)
+{
+	struct gccorecontext *gccorecontext;
+	struct gcqueue *gcqueue;
+	unsigned int triggered;
+
+	/* Read gcregIntrAcknowledge register. */
+	triggered = gc_read_reg(GCREG_INTR_ACKNOWLEDGE_Address);
+
+	/* Return if not our interrupt. */
+	if (triggered == 0)
+		return IRQ_NONE;
+
+	/* Cast the context. */
+	gccorecontext = (struct gccorecontext *) _gccorecontext;
+
+	/* Get a shortcut to the queue object. */
+	gcqueue = &gccorecontext->gcqueue;
+
+	/* Log interrupt data. */
+	gc_debug_cache_gpu_status_from_irq(triggered);
+
+	/* Bus error? */
+	if ((triggered & GC_SIG_MASK_BUS_ERROR) != 0) {
+		triggered &= ~GC_SIG_MASK_BUS_ERROR;
+		complete(&gcqueue->buserror);
+	}
+
+	/* MMU error? */
+	if ((triggered & GC_SIG_MASK_MMU_ERROR) != 0) {
+		triggered &= ~GC_SIG_MASK_MMU_ERROR;
+		complete(&gcqueue->mmuerror);
+	}
+
+	/* Command buffer event? */
+	if (triggered != 0)
+		atomic_add(triggered, &gcqueue->triggered);
+
+	/* Release the command buffer thread. */
+	complete(&gcqueue->ready);
+
+	/* IRQ handled. */
+	return IRQ_HANDLED;
+}
+
+
+/*******************************************************************************
+ * Command buffer event and queue management.
+ */
+
+enum gcerror gcqueue_alloc_event(struct gcqueue *gcqueue,
+				 struct gcevent **gcevent)
+{
+	enum gcerror gcerror = GCERR_NONE;
+	struct gcevent *temp;
+
+	GCENTER(GCZONE_EVENT);
+
+	GCLOCK(&gcqueue->vaceventlock);
+
+	if (list_empty(&gcqueue->vacevents)) {
+		GCDBG(GCZONE_EVENT, "allocating event entry.\n");
+		temp = kmalloc(sizeof(struct gcevent), GFP_KERNEL);
+		if (temp == NULL) {
+			GCERR("event entry allocation failed.\n");
+			gcerror = GCERR_CMD_EVENT_ALLOC;
+			goto exit;
+		}
+	} else {
+		struct list_head *head;
+		head = gcqueue->vacevents.next;
+		temp = list_entry(head, struct gcevent, link);
+		list_del(head);
+	}
+
+	GCDBG(GCZONE_EVENT, "event entry allocated @ 0x%08X.\n",
+	      (unsigned int) temp);
+
+	*gcevent = temp;
+
+exit:
+	GCUNLOCK(&gcqueue->vaceventlock);
+
+	GCEXITARG(GCZONE_EVENT, "gc%s = 0x%08X\n",
+		(gcerror == GCERR_NONE) ? "result" : "error", gcerror);
+	return gcerror;
+}
+
+enum gcerror gcqueue_free_event(struct gcqueue *gcqueue,
+				struct gcevent *gcevent)
+{
+	GCENTER(GCZONE_EVENT);
+
+	GCLOCK(&gcqueue->vaceventlock);
+	list_move(&gcevent->link, &gcqueue->vacevents);
+	GCUNLOCK(&gcqueue->vaceventlock);
+
+	GCEXIT(GCZONE_EVENT);
+	return GCERR_NONE;
+}
+
+enum gcerror gcqueue_alloc_cmdbuf(struct gcqueue *gcqueue,
+				  struct gccmdbuf **gccmdbuf)
+{
+	enum gcerror gcerror = GCERR_NONE;
+	struct gccmdbuf *temp;
+
+	GCENTER(GCZONE_QUEUE);
+
+	GCLOCK(&gcqueue->vacqueuelock);
+
+	if (list_empty(&gcqueue->vacqueue)) {
+		GCDBG(GCZONE_QUEUE, "allocating queue entry.\n");
+		temp = kmalloc(sizeof(struct gccmdbuf), GFP_KERNEL);
+		if (temp == NULL) {
+			GCERR("queue entry allocation failed.\n");
+			gcerror = GCERR_CMD_QUEUE_ALLOC;
+			goto exit;
+		}
+	} else {
+		struct list_head *head;
+		head = gcqueue->vacqueue.next;
+		temp = list_entry(head, struct gccmdbuf, link);
+		list_del(head);
+	}
+
+	INIT_LIST_HEAD(&temp->events);
+
+	GCDBG(GCZONE_EVENT, "queue entry allocated @ 0x%08X.\n",
+	      (unsigned int) temp);
+
+	*gccmdbuf = temp;
+
+exit:
+	GCUNLOCK(&gcqueue->vacqueuelock);
+
+	GCEXITARG(GCZONE_QUEUE, "gc%s = 0x%08X\n",
+		(gcerror == GCERR_NONE) ? "result" : "error", gcerror);
+	return gcerror;
+}
+
+void gcqueue_free_cmdbuf(struct gcqueue *gcqueue,
+			 struct gccmdbuf *gccmdbuf,
+			 unsigned int *flags)
+{
+	struct list_head *head;
+	struct gcevent *gcevent;
+
+	GCENTERARG(GCZONE_QUEUE, "queue entry = 0x%08X\n",
+		   (unsigned int) gccmdbuf);
+
+	/* Have events? */
+	if (!list_empty(&gccmdbuf->events)) {
+		/* Events not expected? */
+		if (flags == NULL)
+			GCERR("buffer has events.\n");
+
+		/* Execute and free all events. */
+		while (!list_empty(&gccmdbuf->events)) {
+			head = gccmdbuf->events.next;
+			gcevent = list_entry(head, struct gcevent, link);
+			gcevent->handler(gcevent, flags);
+			gcqueue_free_event(gcqueue, gcevent);
+		}
+	}
+
+	/* Move the queue entry to the vacant list. */
+	GCLOCK(&gcqueue->vacqueuelock);
+	list_move(&gccmdbuf->link, &gcqueue->vacqueue);
+	GCUNLOCK(&gcqueue->vacqueuelock);
+
+	GCEXIT(GCZONE_QUEUE);
+}
+
+
+/*******************************************************************************
+ * Event handlers.
+ */
+
+/* Completion event. */
+static void event_completion(struct gcevent *gcevent, unsigned int *flags)
+{
+	struct completion *completion;
+
+	GCENTER(GCZONE_EVENT);
+
+	completion = gcevent->event.completion.completion;
+	GCDBG(GCZONE_EVENT, "completion = 0x%08X\n",
+		   (unsigned int) completion);
+
+	complete(completion);
+
+	GCEXIT(GCZONE_EVENT);
+}
+
+/* Callback event. */
+static void event_callback(struct gcevent *gcevent, unsigned int *flags)
+{
+	void (*callback) (void *callbackparam);
+	void *callbackparam;
+
+	GCENTER(GCZONE_EVENT);
+
+	callback = gcevent->event.callback.callback;
+	callbackparam = gcevent->event.callback.callbackparam;
+	GCDBG(GCZONE_EVENT, "callback      = 0x%08X\n",
+		(unsigned int) callback);
+	GCDBG(GCZONE_EVENT, "callbackparam = 0x%08X\n",
+		(unsigned int) callbackparam);
+
+	callback(callbackparam);
+
+	GCEXIT(GCZONE_EVENT);
+}
+
+/* Unmap event. */
+static void event_unmap(struct gcevent *gcevent, unsigned int *flags)
+{
+	enum gcerror gcerror;
+	struct gccorecontext *gccorecontext;
+	struct gcmmucontext *gcmmucontext;
+	struct gcmmuarena *gcmmuarena;
+
+	GCENTER(GCZONE_EVENT);
+
+	gccorecontext = gcevent->event.unmap.gccorecontext;
+	gcmmucontext = gcevent->event.unmap.gcmmucontext;
+	gcmmuarena = gcevent->event.unmap.gcmmuarena;
+
+	GCDBG(GCZONE_EVENT, "arena = 0x%08X\n",
+		(unsigned int) gcmmuarena);
+
+	gcerror = gcmmu_unmap(gccorecontext, gcmmucontext, gcmmuarena);
+	if (gcerror != GCERR_NONE)
+		GCERR("failed to unmap 0x%08X (gcerror = 0x%08X).\n",
+		      gcmmuarena, gcerror);
+
+	GCEXIT(GCZONE_EVENT);
+}
+
+
+/*******************************************************************************
+ * Command buffer thread.
+ */
+
+enum gcerror gcqueue_alloc_int(struct gcqueue *gcqueue,
+			       unsigned int *interrupt)
+{
+	unsigned int i;
+
+	GCENTER(GCZONE_INTERRUPT);
+
+	/* Wait until there are available interrupts. */
+	GCWAIT_FOR_COMPLETION(&gcqueue->freeint);
+
+	/* Get acceess to the interrupt tracker. */
+	GCLOCK(&gcqueue->intusedlock);
+
+	/* Find the first available interrupt. */
+	for (i = 0; i < countof(gcqueue->intused); i += 1)
+		if (!gcqueue->intused[i]) {
+			gcqueue->intused[i] = true;
+
+			/* Release access to the interrupt tracker. */
+			GCUNLOCK(&gcqueue->intusedlock);
+			*interrupt = i;
+
+			GCEXITARG(GCZONE_INTERRUPT, "interrupt = %d.\n", i);
+			return GCERR_NONE;
+		}
+
+	/* Release access to the interrupt tracker. */
+	GCUNLOCK(&gcqueue->intusedlock);
+
+	/* This is unexpected. */
+	GCERR("unexpected condition.");
+
+	GCEXIT(GCZONE_INTERRUPT);
+	return GCERR_CMD_INT_ALLOC;
+}
+
+static void free_interrupt(struct gcqueue *gcqueue, unsigned int interrupt)
+{
+	GCENTERARG(GCZONE_INTERRUPT, "interrupt = %d.\n", interrupt);
+
+	GCLOCK(&gcqueue->intusedlock);
+
+	if (!gcqueue->intused[interrupt]) {
+		GCERR("interrupt %d is already free.\n", interrupt);
+		GCUNLOCK(&gcqueue->intusedlock);
+	} else {
+		gcqueue->intused[interrupt] = false;
+		GCUNLOCK(&gcqueue->intusedlock);
+
+		complete(&gcqueue->freeint);
+	}
+
+	GCEXIT(GCZONE_INTERRUPT);
+}
+
+static void link_queue(struct list_head *newlist,
+		       struct list_head *queue,
+		       struct gcmoterminator *gcmoterminator)
+{
+	struct list_head *head;
+	struct gccmdbuf *gccmdbuf;
+	struct gccmdlink gccmdlink;
+
+	GCENTER(GCZONE_QUEUE);
+
+	if (!list_empty(queue)) {
+		GCDBG(GCZONE_QUEUE, "main queue is not empty.\n");
+
+		/* Get the tail of the queue. */
+		head = queue->prev;
+		gccmdbuf = list_entry(head, struct gccmdbuf, link);
+		gcmoterminator = gccmdbuf->gcmoterminator;
+
+		/* Link the tail command buffer from the specified queue to
+		 * the first command buffer in the specified list. If the tail
+		 * command buffer has no events associated with it, the
+		 * interrupt is not needed. */
+		if (list_empty(&gccmdbuf->events)) {
+			/* Replace EVENT with a NOP. */
+			GCDBG_QUEUE(GCZONE_QUEUE, "removing interrupt from ",
+				    gccmdbuf);
+			gcmoterminator->u1.nop.cmd.raw = gccmdnop_const.cmd.raw;
+			mb();
+		}
+	}
+
+	if (gcmoterminator != NULL) {
+		GCDBG(GCZONE_QUEUE, "modifying the terminator @ 0x%08X.\n",
+		      gcmoterminator);
+
+		/* Get the head of the list. */
+		head = newlist->next;
+		gccmdbuf = list_entry(head, struct gccmdbuf, link);
+
+		/* Configure new command word. */
+		gccmdlink.cmd.raw = 0;
+		gccmdlink.cmd.fld.count = gccmdbuf->count;
+		gccmdlink.cmd.fld.opcode = GCREG_COMMAND_OPCODE_LINK;
+
+		/* Change WAIT into a LINK command; write the address first. */
+		gcmoterminator->u2.linknext.address = gccmdbuf->physical;
+		mb();
+		gcmoterminator->u2.linknext.cmd.raw = gccmdlink.cmd.raw;
+		mb();
+	}
+
+	/* Merge the list to the end of the queue. */
+	list_splice_tail_init(newlist, queue);
+
+	GCEXIT(GCZONE_QUEUE);
+}
+
+static enum gcerror append_cmdbuf(
+	struct gccorecontext *gccorecontext,
+	struct gcqueue *gcqueue)
+{
+	enum gcerror gcerror = GCERR_NONE;
+	struct gccmdbuf *headcmdbuf, *tailcmdbuf;
+	struct list_head *head, *tail;
+
+	/* Dump scheduled command buffers. */
+#if GCDEBUG_ENABLE
+	list_for_each(head, &gcqueue->cmdbufhead) {
+		headcmdbuf = list_entry(head, struct gccmdbuf, link);
+
+		GCDUMPBUFFER(GCZONE_BUFFER,
+			     headcmdbuf->logical,
+			     headcmdbuf->physical,
+			     headcmdbuf->size);
+	}
+#endif
+
+	GCLOCK(&gcqueue->queuelock);
+
+	/* Link the tail of the active command buffer to
+	 * the first scheduled command buffer. */
+	link_queue(&gcqueue->cmdbufhead, &gcqueue->queue,
+		   gcqueue->gcmoterminator);
+
+	/* Get the last entry from the active queue. */
+	tail = gcqueue->queue.prev;
+	tailcmdbuf = list_entry(tail, struct gccmdbuf, link);
+
+	/* Update the tail pointer. */
+	gcqueue->gcmoterminator = tailcmdbuf->gcmoterminator;
+
+	/* Start the GPU if not already running. */
+	if (try_wait_for_completion(&gcqueue->stopped)) {
+		GCDBG(GCZONE_THREAD, "GPU is currently stopped - starting.\n");
+
+		/* Enable power to the chip. */
+		gcpwr_set(gccorecontext, GCPWR_ON);
+
+		/* Eable MMU. */
+		gcerror = gcmmu_enable(gccorecontext, gcqueue);
+		if (gcerror != GCERR_NONE) {
+			GCERR("failed to enable MMU.\n");
+			goto exit;
+		}
+
+		/* Get the first entry from the active queue. */
+		head = gcqueue->queue.next;
+		headcmdbuf = list_entry(head, struct gccmdbuf, link);
+
+		GCDBG_QUEUE(GCZONE_THREAD, "starting ", headcmdbuf);
+
+		/* Enable all events. */
+		gc_write_reg(GCREG_INTR_ENBL_Address, ~0U);
+
+		/* Write address register. */
+		gc_write_reg(GCREG_CMD_BUFFER_ADDR_Address,
+			     headcmdbuf->physical);
+
+		/* Write control register. */
+		gc_write_reg(GCREG_CMD_BUFFER_CTRL_Address,
+			     GCSETFIELDVAL(0, GCREG_CMD_BUFFER_CTRL,
+					   ENABLE, ENABLE) |
+			     GCSETFIELD(0, GCREG_CMD_BUFFER_CTRL,
+					PREFETCH, headcmdbuf->count));
+
+		/* Release the command buffer thread. */
+		complete(&gcqueue->ready);
+	}
+
+exit:
+	/* Unlock queue acccess. */
+	GCUNLOCK(&gcqueue->queuelock);
+
+	return gcerror;
+}
+
+static int gccmdthread(void *_gccorecontext)
+{
+	struct gccorecontext *gccorecontext;
+	struct gcqueue *gcqueue;
+	unsigned long timeout, signaled;
+	unsigned int i, triggered, ints2process, intmask;
+	struct list_head *head;
+	struct gccmdbuf *headcmdbuf;
+	unsigned int flags;
+	unsigned int dmapc, pc1, pc2;
+
+	GCDBG(GCZONE_THREAD, "context = 0x%08X\n",
+		   (unsigned int) _gccorecontext);
+
+	/* Cast the context. */
+	gccorecontext = (struct gccorecontext *) _gccorecontext;
+
+	/* Get a shortcut to the queue object. */
+	gcqueue = &gccorecontext->gcqueue;
+
+	GCDBG(GCZONE_THREAD, "starting command queue thread.\n");
+
+	/* Set initial timeout to infinity since at this point GPU is
+	 * considered to be powered off and there is no work pending or
+	 * in progress yet. */
+	timeout = MAX_SCHEDULE_TIMEOUT;
+
+	/* Main thread loop. */
+	while (true) {
+		/* Wait for ready signal. If 'ready' is signaled before the
+		 * call times out, signaled is set to a value greater then
+		 * zero. If the call times out, signaled is set to zero. */
+		signaled = wait_for_completion_interruptible_timeout(
+			&gcqueue->ready, timeout);
+		GCDBG(GCZONE_THREAD, "wait(ready) = %d.\n", signaled);
+
+		if (signaled < 0)
+			continue;
+
+		/* Get triggered interrupts. */
+		ints2process = triggered = atomic_read(&gcqueue->triggered);
+		GCDBG(GCZONE_THREAD, "int = 0x%08X.\n", triggered);
+
+		GCLOCK(&gcqueue->queuelock);
+
+		/* Reset execution control flags. */
+		flags = 0;
+
+		/* Process triggered interrupts. */
+		while (ints2process != 0) {
+			GCDBG(GCZONE_INTERRUPT, "ints2process = 0x%08X.\n",
+			      ints2process);
+
+			/* Queue empty? */
+			if (list_empty(&gcqueue->queue)) {
+				GCERR("no match for triggered ints 0x%08X.\n",
+				      ints2process);
+
+				/* Reset triggered interrupts. */
+				atomic_sub(triggered, &gcqueue->triggered);
+				GCDBG(GCZONE_INTERRUPT, "triggered = 0x%08X.\n",
+				      atomic_read(&gcqueue->triggered));
+
+				/* Free triggered interrupts. */
+				for (i = 0, intmask = 1; ints2process != 0;
+					i += 1, intmask <<= 1) {
+					GCDBG(GCZONE_INTERRUPT,
+					      "ints2process = 0x%08X.\n",
+					      ints2process);
+					GCDBG(GCZONE_INTERRUPT,
+					      "intmask = 0x%08X (%d).\n",
+					      intmask, i);
+
+					if ((ints2process & intmask) != 0) {
+						free_interrupt(gcqueue, i);
+						ints2process &= ~intmask;
+					}
+				}
+
+				break;
+			}
+
+			/* Get the head entry from the queue. */
+			head = gcqueue->queue.next;
+			headcmdbuf = list_entry(head, struct gccmdbuf, link);
+
+			GCDBG_QUEUE(GCZONE_THREAD, "processing ", headcmdbuf);
+
+			/* Buffer with no events? */
+			if (headcmdbuf->interrupt == ~0U) {
+				GCDBG(GCZONE_THREAD,
+				      "buffer has no interrupt.\n");
+
+				/* Free the entry. */
+				gcqueue_free_cmdbuf(gcqueue, headcmdbuf, NULL);
+				continue;
+			}
+
+			/* Compute interrupt mask for the buffer. */
+			intmask = 1 << headcmdbuf->interrupt;
+			GCDBG(GCZONE_INTERRUPT, "intmask = 0x%08X.\n", intmask);
+
+			/* Did interrupt happen for the head entry? */
+			if ((ints2process & intmask) != 0) {
+				ints2process &= ~intmask;
+				GCDBG(GCZONE_INTERRUPT,
+				      "ints2process = 0x%08X\n", ints2process);
+
+				atomic_sub(intmask, &gcqueue->triggered);
+				GCDBG(GCZONE_INTERRUPT, "triggered = 0x%08X.\n",
+				      atomic_read(&gcqueue->triggered));
+			} else {
+				if (list_empty(&headcmdbuf->events)) {
+					GCDBG(GCZONE_THREAD,
+					      "possibility of a lost "
+					      "interrupt %d.\n",
+					      headcmdbuf->interrupt);
+				} else {
+					GCERR("lost interrupt %d.\n",
+					      headcmdbuf->interrupt);
+				}
+			}
+
+			/* Free the interrupt. */
+			free_interrupt(gcqueue, headcmdbuf->interrupt);
+
+			/* Execute events if any and free the entry. */
+			gcqueue_free_cmdbuf(gcqueue, headcmdbuf, &flags);
+		}
+
+		GCUNLOCK(&gcqueue->queuelock);
+
+		/* Bus error? */
+		if (try_wait_for_completion(&gcqueue->buserror)) {
+			GCERR("bus error detected.\n");
+			GCGPUSTATUS();
+
+			GCLOCK(&gcqueue->queuelock);
+
+			/* Execute all pending events. */
+			while (!list_empty(&gcqueue->queue)) {
+				head = gcqueue->queue.next;
+				headcmdbuf = list_entry(head,
+							struct gccmdbuf,
+							link);
+
+				/* Execute events if any and free the entry. */
+				gcqueue_free_cmdbuf(gcqueue, headcmdbuf,
+						    &flags);
+			}
+
+			GCUNLOCK(&gcqueue->queuelock);
+
+			/* Reset GPU. */
+			gcpwr_reset(gccorecontext);
+			continue;
+		}
+
+		/* MMU error? */
+		if (try_wait_for_completion(&gcqueue->mmuerror)) {
+			static char *mmuerror[] = {
+				"  no error",
+				"  slave not present",
+				"  page not present",
+				"  write violation"
+			};
+
+			unsigned int mmustatus, mmucode;
+			unsigned int mmuaddress;
+			unsigned int mtlb, stlb, offset;
+
+			mmustatus = gc_read_reg(GCREG_MMU_STATUS_Address);
+			GCERR("MMU error detected; status = 0x%08X.\n",
+			      mmustatus);
+
+			for (i = 0; i < 4; i += 1) {
+				mmucode = mmustatus & 0xF;
+				mmustatus >>= 4;
+
+				if (mmucode == 0)
+					continue;
+
+				GCERR("MMU%d is at fault:\n", i);
+				if (mmucode >= countof(mmuerror))
+					GCERR("  unknown state %d.\n", mmucode);
+				else
+					GCERR("%s.\n", mmuerror[mmucode]);
+
+				mmuaddress = gc_read_reg(
+					GCREG_MMU_EXCEPTION_Address + i);
+
+				mtlb = (mmuaddress & GCMMU_MTLB_MASK)
+				     >> GCMMU_MTLB_SHIFT;
+				stlb = (mmuaddress & GCMMU_STLB_MASK)
+				     >> GCMMU_STLB_SHIFT;
+				offset =  mmuaddress & GCMMU_OFFSET_MASK;
+
+				GCERR("  address = 0x%08X\n", mmuaddress);
+				GCERR("	 mtlb    = %d\n", mtlb);
+				GCERR("	 stlb    = %d\n", stlb);
+				GCERR("	 offset  = 0x%08X (%d)\n",
+				      offset, offset);
+
+				/* Route the invalid access to the safe zone. */
+				gc_write_reg(GCREG_MMU_EXCEPTION_Address + i,
+					gccorecontext->gcmmu.safezonephys);
+
+				GCERR("	 rcovery address = 0x%08X\n",
+				      gccorecontext->gcmmu.safezonephys);
+			}
+
+			continue;
+		}
+
+		/* Need to start FE? */
+		if ((flags & GC_CMDBUF_START_FE) != 0) {
+			GCLOCK(&gcqueue->queuelock);
+
+			/* Get the first entry from the active queue. */
+			head = gcqueue->queue.next;
+			headcmdbuf = list_entry(head,
+						struct gccmdbuf,
+						link);
+
+			GCDBG_QUEUE(GCZONE_THREAD, "restarting ", headcmdbuf);
+
+			/* Write address register. */
+			gc_write_reg(GCREG_CMD_BUFFER_ADDR_Address,
+					headcmdbuf->physical);
+
+			/* Write control register. */
+			gc_write_reg(GCREG_CMD_BUFFER_CTRL_Address,
+				GCSETFIELDVAL(0, GCREG_CMD_BUFFER_CTRL,
+					ENABLE, ENABLE) |
+				GCSETFIELD(0, GCREG_CMD_BUFFER_CTRL,
+					PREFETCH, headcmdbuf->count));
+
+			GCUNLOCK(&gcqueue->queuelock);
+			continue;
+		}
+
+		if (signaled && !gcqueue->suspend) {
+			/* The timeout value controls when the power
+			 * on the GPU is pulled if there is no activity
+			 * in progress or scheduled. */
+			timeout = msecs_to_jiffies(GC_THREAD_TIMEOUT);
+		} else {
+			GCLOCK(&gcqueue->queuelock);
+
+			if (gcqueue->suspend)
+				GCDBG(GCZONE_THREAD, "suspend requested\n");
+
+			if (!signaled)
+				GCDBG(GCZONE_THREAD, "thread timedout.\n");
+
+			if (gcqueue->gcmoterminator == NULL) {
+				GCDBG(GCZONE_THREAD, "no work scheduled.\n");
+
+				if (!list_empty(&gcqueue->queue))
+					GCERR("queue is not empty.\n");
+
+				gcqueue->suspend = false;
+
+				/* Set timeout to infinity. */
+				timeout = MAX_SCHEDULE_TIMEOUT;
+
+				GCUNLOCK(&gcqueue->queuelock);
+				continue;
+			}
+
+			/* Determine PC range for the terminatior. */
+			pc1 = gcqueue->gcmoterminator->u3.linkwait.address;
+			pc2 = pc1
+			    + sizeof(struct gccmdwait)
+			    + sizeof(struct gccmdlink);
+
+			/* Check to see if the FE reached the terminatior. */
+			dmapc = gc_read_reg(GCREG_FE_DEBUG_CUR_CMD_ADR_Address);
+			if ((dmapc < pc1) || (dmapc > pc2)) {
+				/* Haven't reached yet. */
+				GCDBG(GCZONE_THREAD,
+				      "execution hasn't reached the end; "
+				      "large amount of work?\n");
+				GCDBG(GCZONE_THREAD,
+				      "current location @ 0x%08X.\n",
+				      dmapc);
+				GCUNLOCK(&gcqueue->queuelock);
+				continue;
+			}
+
+			/* Free the queue. */
+			while (!list_empty(&gcqueue->queue)) {
+				head = gcqueue->queue.next;
+				headcmdbuf = list_entry(head,
+							struct gccmdbuf,
+							link);
+
+				if (!list_empty(&headcmdbuf->events)) {
+					/* Found events, there must be
+					 * pending interrupts. */
+					break;
+				}
+
+				/* Free the entry. */
+				gcqueue_free_cmdbuf(gcqueue, headcmdbuf,
+						    NULL);
+			}
+
+			if (!list_empty(&gcqueue->queue)) {
+				GCDBG(GCZONE_THREAD,
+				      "aborting shutdown to process events\n");
+				GCUNLOCK(&gcqueue->queuelock);
+				continue;
+			}
+
+			GCDBG(GCZONE_THREAD,
+			      "execution finished, shutting down.\n");
+
+			/* Convert WAIT to END. */
+			gcqueue->gcmoterminator->u2.end.cmd.raw
+				= gccmdend_const.cmd.raw;
+			mb();
+
+			gcqueue->gcmoterminator = NULL;
+
+			/* Go to suspend. */
+			gcpwr_set(gccorecontext, GCPWR_OFF);
+
+			/* Set idle state. */
+			complete(&gcqueue->stopped);
+
+			gcqueue->suspend = false;
+
+			/* Set timeout to infinity. */
+			timeout = MAX_SCHEDULE_TIMEOUT;
+
+			GCUNLOCK(&gcqueue->queuelock);
+
+			/* Is termination requested? */
+			if (try_wait_for_completion(&gcqueue->stop)) {
+				GCDBG(GCZONE_THREAD,
+				      "terminating command queue thread.\n");
+				break;
+			}
+		}
+	}
+
+	GCDBG(GCZONE_THREAD, "thread exiting.\n");
+	return 0;
+}
+
+/*******************************************************************************
+ * Command buffer API.
+ */
+
+enum gcerror gcqueue_start(struct gccorecontext *gccorecontext)
+{
+	enum gcerror gcerror;
+	struct gcqueue *gcqueue;
+	struct gccmdstorage *storage;
+	unsigned int i;
+
+	GCENTERARG(GCZONE_INIT, "context = 0x%08X\n",
+		   (unsigned int) gccorecontext);
+
+	/* Get a shortcut to the queue object. */
+	gcqueue = &gccorecontext->gcqueue;
+
+	/* Reset the queue object. */
+	memset(gcqueue, 0, sizeof(struct gcqueue));
+
+	/* ISR not installed yet. */
+	gcqueue->isrroutine = -1;
+
+	/* Initialize all storage buffers. */
+	for (i = 0; i < GC_STORAGE_COUNT; i += 1) {
+		/* Get a shortcut to the current storage buffer. */
+		storage = &gcqueue->storagearray[i];
+
+		/* Allocate storage buffer. */
+		gcerror = gc_alloc_noncached(&storage->page, GC_STORAGE_SIZE);
+		if (gcerror != GCERR_NONE) {
+			gcerror = GCERR_SETGRP(gcerror, GCERR_CMD_ALLOC);
+			goto fail;
+		}
+
+		/* Reset buffer info. */
+		storage->physical = storage->page.physical;
+		storage->mapped = 0;
+
+		init_completion(&storage->ready);
+		complete(&storage->ready);
+
+		GCDBG(GCZONE_INIT, "storage buffer [%d] allocated:\n", i);
+		GCDBG(GCZONE_INIT, "  physical = 0x%08X\n", storage->physical);
+		GCDBG(GCZONE_INIT, "  logical = 0x%08X\n",
+		      (unsigned int) storage->page.logical);
+		GCDBG(GCZONE_INIT, "  size = %d\n", storage->page.size);
+	}
+
+	/* Set the current storage buffer. */
+	gcqueue->dirtystorage = true;
+	gcqueue->curstorageidx = 0;
+	gcqueue->curstorage = &gcqueue->storagearray[gcqueue->curstorageidx];
+
+	/* Initialize current allocation info. */
+	gcqueue->logical = (unsigned char *) gcqueue->curstorage->page.logical;
+	gcqueue->physical = gcqueue->curstorage->physical;
+	gcqueue->available = gcqueue->curstorage->page.size - GC_TAIL_RESERVE;
+
+	/* Initialize interrupt tracking. */
+	GCLOCK_INIT(&gcqueue->intusedlock);
+	atomic_set(&gcqueue->triggered, 0);
+
+	/* Mark all interrupts as available. */
+	init_completion(&gcqueue->freeint);
+	for (i = 0; i < countof(gcqueue->intused); i += 1)
+		complete(&gcqueue->freeint);
+
+	/* Set GPU running state. */
+	init_completion(&gcqueue->stopped);
+	complete(&gcqueue->stopped);
+
+	/* Initialize sleep completion. */
+	init_completion(&gcqueue->sleep);
+
+	/* Initialize thread control completions. */
+	init_completion(&gcqueue->ready);
+	init_completion(&gcqueue->stop);
+	init_completion(&gcqueue->stall);
+
+	/* Initialize error signals. */
+	init_completion(&gcqueue->mmuerror);
+	init_completion(&gcqueue->buserror);
+
+	/* Initialize the current command buffer entry. */
+	INIT_LIST_HEAD(&gcqueue->cmdbufhead);
+
+	/* Initialize the schedule and active queue. */
+	INIT_LIST_HEAD(&gcqueue->queue);
+	GCLOCK_INIT(&gcqueue->queuelock);
+
+	/* Initialize entry cache. */
+	INIT_LIST_HEAD(&gcqueue->vacevents);
+	INIT_LIST_HEAD(&gcqueue->vacqueue);
+	GCLOCK_INIT(&gcqueue->vaceventlock);
+	GCLOCK_INIT(&gcqueue->vacqueuelock);
+
+	/* Reset MMU flush state. */
+	gcqueue->flushlogical = NULL;
+
+	/* Install ISR. */
+	gcqueue->isrroutine = request_irq(gccorecontext->irqline, gcisr,
+					  IRQF_SHARED, GC_DEV_NAME,
+					  gccorecontext);
+	if (gcqueue->isrroutine < 0) {
+		GCERR("failed to install ISR (%d).\n", gcqueue->isrroutine);
+		gcerror = GCERR_CMD_ISR;
+		goto fail;
+	}
+
+	GCDBG(GCZONE_INIT, "starting the command queue thread.\n");
+	gcqueue->cmdthread = kthread_create(gccmdthread, gccorecontext,
+						"gccmdthread");
+	if (IS_ERR(gcqueue->cmdthread)) {
+		GCERR("failed to start command thread.\n");
+		gcqueue->cmdthread = NULL;
+		gcerror = GCERR_CMD_THREAD;
+		goto fail;
+	}
+
+	wake_up_process(gcqueue->cmdthread);
+
+	GCEXIT(GCZONE_INIT);
+	return GCERR_NONE;
+
+fail:
+	gcqueue_stop(gccorecontext);
+	GCEXITARG(GCZONE_INIT, "gcerror = 0x%08X\n", gcerror);
+	return gcerror;
+}
+
+enum gcerror gcqueue_stop(struct gccorecontext *gccorecontext)
+{
+	struct gcqueue *gcqueue;
+	struct gccmdstorage *storage;
+	struct list_head *head;
+	struct gccmdbuf *gccmdbuf;
+	struct gcevent *gcevent;
+	unsigned int i;
+
+	GCENTERARG(GCZONE_INIT, "context = 0x%08X\n",
+		   (unsigned int) gccorecontext);
+
+	/* Get a shortcut to the queue object. */
+	gcqueue = &gccorecontext->gcqueue;
+
+	/* Stop the command buffer thread. */
+	if (gcqueue->cmdthread != NULL) {
+		GCDBG(GCZONE_INIT, "stopping the command queue thread.\n");
+		complete(&gcqueue->stop);
+		complete(&gcqueue->ready);
+		kthread_stop(gcqueue->cmdthread);
+		gcqueue->cmdthread = NULL;
+		GCDBG(GCZONE_INIT, "command queue thread stopped.\n");
+	}
+
+	/* Remove ISR routine. */
+	if (gcqueue->isrroutine == 0) {
+		GCDBG(GCZONE_ISR, "removing ISR.\n");
+		free_irq(gccorecontext->irqline, gccorecontext);
+		gcqueue->isrroutine = -1;
+	}
+
+	/* Free all storage buffers. */
+	for (i = 0; i < GC_STORAGE_COUNT; i += 1) {
+		/* Get a shortcut to the current storage buffer. */
+		storage = &gcqueue->storagearray[i];
+
+		/* Verify that the storage buffer is not mapped. */
+		if (storage->mapped != 0)
+			GCERR("storage buffer is mapped.\n");
+
+		/* Free the buffer. */
+		if (storage->page.logical != NULL) {
+			gc_free_noncached(&storage->page);
+			storage->physical = ~0U;
+		}
+	}
+
+	/* Reset current buffer info. */
+	gcqueue->logical = NULL;
+	gcqueue->physical = ~0U;
+	gcqueue->available = 0;
+
+	/* Free the current command buffer. */
+	while (!list_empty(&gcqueue->cmdbufhead)) {
+		head = gcqueue->cmdbufhead.next;
+		gccmdbuf = list_entry(head, struct gccmdbuf, link);
+		gcqueue_free_cmdbuf(gcqueue, gccmdbuf, NULL);
+	}
+
+	/* Free command queue entries. */
+	while (!list_empty(&gcqueue->queue)) {
+		head = gcqueue->queue.next;
+		gccmdbuf = list_entry(head, struct gccmdbuf, link);
+		gcqueue_free_cmdbuf(gcqueue, gccmdbuf, NULL);
+	}
+
+	/* Free vacant entry lists. */
+	while (!list_empty(&gcqueue->vacevents)) {
+		head = gcqueue->vacevents.next;
+		gcevent = list_entry(head, struct gcevent, link);
+		list_del(head);
+		kfree(gcevent);
+	}
+
+	while (!list_empty(&gcqueue->vacqueue)) {
+		head = gcqueue->vacqueue.next;
+		gccmdbuf = list_entry(head, struct gccmdbuf, link);
+		list_del(head);
+		kfree(gccmdbuf);
+	}
+
+	GCEXIT(GCZONE_INIT);
+	return GCERR_NONE;
+}
+
+enum gcerror gcqueue_map(struct gccorecontext *gccorecontext,
+				struct gcmmucontext *gcmmucontext)
+{
+	enum gcerror gcerror;
+	struct gcqueue *gcqueue;
+	struct gccmdstorage *gccmdstorage;
+	struct gcmmuphysmem mem;
+	pte_t physpages[GC_STORAGE_PAGES];
+	unsigned int i, j, physical;
+
+	GCENTERARG(GCZONE_MAPPING, "context = 0x%08X\n",
+		   (unsigned int) gccorecontext);
+
+	/* Get a shortcut to the queue object. */
+	gcqueue = &gccorecontext->gcqueue;
+
+	/* Map all command buffers. */
+	for (i = 0; i < GC_STORAGE_COUNT; i += 1) {
+		/* Get a shortcut to the current storage buffer. */
+		gccmdstorage = &gcqueue->storagearray[i];
+
+		/* Make sure command buffer hasn't been mapped yet. */
+		if (gcmmucontext->storagearray[i] != NULL) {
+			GCERR("storage %d is already mapped.\n", i);
+			gcerror = GCERR_CMD_MAPPED;
+			goto fail;
+		}
+
+		GCDBG(GCZONE_MAPPING, "maping storage %d.\n", i);
+		GCDBG(GCZONE_MAPPING, "  physical = 0x%08X\n",
+		      gccmdstorage->page.physical);
+		GCDBG(GCZONE_MAPPING, "  logical = 0x%08X\n",
+		      (unsigned int) gccmdstorage->page.logical);
+		GCDBG(GCZONE_MAPPING, "  size = %d\n",
+		      gccmdstorage->page.size);
+
+		/* Get physical pages. */
+		physical = gccmdstorage->page.physical;
+		for (j = 0; j < GC_STORAGE_PAGES; j += 1) {
+			physpages[j] = physical;
+			physical += PAGE_SIZE;
+		}
+
+		/* Map the buffer. */
+		mem.base = 0;
+		mem.offset = 0;
+		mem.count = GC_STORAGE_PAGES;
+		mem.pages = physpages;
+		mem.pagesize = PAGE_SIZE;
+
+		gcerror = gcmmu_map(gccorecontext, gcmmucontext, &mem,
+				    &gcmmucontext->storagearray[i]);
+		if (gcerror != 0) {
+			GCERR("failed to map storage %d.\n", i);
+			goto fail;
+		}
+
+		physical = gcmmucontext->storagearray[i]->address;
+		if (gccmdstorage->mapped) {
+			GCDBG(GCZONE_MAPPING,
+			      "  storage %d is already mapped.\n", i);
+
+			if (gccmdstorage->physical != physical) {
+				GCERR("storage %d, inconsistent mapping!\n", i);
+				gcerror = GCERR_CMD_CONSISTENCY;
+				goto fail;
+			}
+		} else {
+			GCDBG(GCZONE_MAPPING,
+			      "  mapped storage %d @ 0x%08X.\n",
+			      i, physical);
+
+			/* Not mapped yet, replace the physical address with
+			 * the mapped one. */
+			gccmdstorage->physical = physical;
+
+			/* Update the allocatable address. */
+			if (gccmdstorage == gcqueue->curstorage) {
+				gcqueue->physical = gccmdstorage->physical;
+				GCDBG(GCZONE_MAPPING,
+				      "  setting current physical address.\n");
+			}
+		}
+
+		gccmdstorage->mapped += 1;
+	}
+
+	GCEXIT(GCZONE_MAPPING);
+	return GCERR_NONE;
+
+fail:
+	gcqueue_unmap(gccorecontext, gcmmucontext);
+	GCEXITARG(GCZONE_MAPPING, "gcerror = 0x%08X\n", gcerror);
+	return gcerror;
+}
+
+enum gcerror gcqueue_unmap(struct gccorecontext *gccorecontext,
+				struct gcmmucontext *gcmmucontext)
+{
+	enum gcerror gcerror;
+	struct gcqueue *gcqueue;
+	struct gccmdstorage *gccmdstorage;
+	unsigned int i;
+
+	GCENTERARG(GCZONE_MAPPING, "context = 0x%08X\n",
+		   (unsigned int) gccorecontext);
+
+	/* Get a shortcut to the queue object. */
+	gcqueue = &gccorecontext->gcqueue;
+
+	/* Map all command buffers. */
+	for (i = 0; i < GC_STORAGE_COUNT; i += 1) {
+		/* Get a shortcut to the current command buffer structure. */
+		gccmdstorage = &gcqueue->storagearray[i];
+
+		/* Make sure command buffer is mapped. */
+		if (gcmmucontext->storagearray[i] == NULL)
+			continue;
+
+		gcerror = gcmmu_unmap(gccorecontext, gcmmucontext,
+				      gcmmucontext->storagearray[i]);
+		if (gcerror != 0) {
+			GCERR("failed to unmap command buffer %d.\n", i);
+			goto fail;
+		}
+
+		/* Reset mapping. */
+		gcmmucontext->storagearray[i] = NULL;
+		gccmdstorage->mapped -= 1;
+	}
+
+	GCEXIT(GCZONE_MAPPING);
+	return GCERR_NONE;
+
+fail:
+	GCEXITARG(GCZONE_MAPPING, "gcerror = 0x%08X\n", gcerror);
+	return gcerror;
+}
+
+enum gcerror gcqueue_callback(struct gccorecontext *gccorecontext,
+			      struct gcmmucontext *gcmmucontext,
+			      void (*callback) (void *callbackparam),
+			      void *callbackparam)
+{
+	enum gcerror gcerror = GCERR_NONE;
+	struct gcqueue *gcqueue;
+	struct gccmdbuf *gccmdbuf;
+	struct list_head *head;
+	struct gcevent *gcevent;
+
+	GCENTER(GCZONE_EVENT);
+
+	/* Get a shortcut to the queue object. */
+	gcqueue = &gccorecontext->gcqueue;
+
+	/* Allocate command buffer. */
+	if (list_empty(&gcqueue->cmdbufhead)) {
+		gcerror = gcqueue_alloc(gccorecontext, gcmmucontext,
+					0, NULL, NULL);
+		if (gcerror != GCERR_NONE)
+			goto exit;
+	}
+
+	/* Get the current command buffer. */
+	head = gcqueue->cmdbufhead.prev;
+	gccmdbuf = list_entry(head, struct gccmdbuf, link);
+
+	/* Add callback event. */
+	gcerror = gcqueue_alloc_event(gcqueue, &gcevent);
+	if (gcerror != GCERR_NONE)
+		goto exit;
+
+	/* Initialize the event and add to the list. */
+	gcevent->handler = event_callback;
+	gcevent->event.callback.callback = callback;
+	gcevent->event.callback.callbackparam = callbackparam;
+	list_add_tail(&gcevent->link, &gccmdbuf->events);
+
+	GCDBG(GCZONE_EVENT, "callback      = 0x%08X\n",
+		(unsigned int) callback);
+	GCDBG(GCZONE_EVENT, "callbackparam = 0x%08X\n",
+		(unsigned int) callbackparam);
+
+exit:
+	GCEXIT(GCZONE_EVENT);
+	return gcerror;
+}
+
+enum gcerror gcqueue_schedunmap(struct gccorecontext *gccorecontext,
+				struct gcmmucontext *gcmmucontext,
+				unsigned long handle)
+{
+	enum gcerror gcerror = GCERR_NONE;
+	struct gcqueue *gcqueue;
+	struct gccmdbuf *gccmdbuf;
+	struct list_head *head;
+	struct gcevent *gcevent;
+
+	GCENTER(GCZONE_EVENT);
+
+	/* Get a shortcut to the queue object. */
+	gcqueue = &gccorecontext->gcqueue;
+
+	/* Allocate command buffer. */
+	if (list_empty(&gcqueue->cmdbufhead)) {
+		gcerror = gcqueue_alloc(gccorecontext, gcmmucontext,
+					0, NULL, NULL);
+		if (gcerror != GCERR_NONE)
+			goto exit;
+	}
+
+	/* Get the current command buffer. */
+	head = gcqueue->cmdbufhead.prev;
+	gccmdbuf = list_entry(head, struct gccmdbuf, link);
+
+	/* Add callback event. */
+	gcerror = gcqueue_alloc_event(gcqueue, &gcevent);
+	if (gcerror != GCERR_NONE)
+		goto exit;
+
+	/* Initialize the event and add to the list. */
+	gcevent->handler = event_unmap;
+	gcevent->event.unmap.gccorecontext = gccorecontext;
+	gcevent->event.unmap.gcmmucontext = gcmmucontext;
+	gcevent->event.unmap.gcmmuarena = (struct gcmmuarena *) handle;
+	list_add_tail(&gcevent->link, &gccmdbuf->events);
+
+	GCDBG(GCZONE_EVENT, "handle = 0x%08X\n", handle);
+
+exit:
+	GCEXIT(GCZONE_EVENT);
+	return gcerror;
+}
+
+enum gcerror gcqueue_alloc(struct gccorecontext *gccorecontext,
+			   struct gcmmucontext *gcmmucontext,
+			   unsigned int size,
+			   void **logical,
+			   unsigned int *physical)
+{
+	enum gcerror gcerror = GCERR_NONE;
+	struct gcqueue *gcqueue;
+	struct gccmdbuf *gccmdbuf;
+	struct list_head *head;
+
+	GCENTERARG(GCZONE_ALLOC, "context = 0x%08X, size = %d\n",
+		   (unsigned int) gccorecontext, size);
+
+	/* Get a shortcut to the queue object. */
+	gcqueue = &gccorecontext->gcqueue;
+
+	while (true) {
+		/* Wait until the storage buffer becomes available. */
+		if (gcqueue->dirtystorage) {
+			if (!try_wait_for_completion(
+					&gcqueue->curstorage->ready)) {
+				GCDBG(GCZONE_ALLOC,
+					"waiting for the storage buffer"
+					" to become available.\n");
+
+				GCWAIT_FOR_COMPLETION(
+					&gcqueue->curstorage->ready);
+			}
+
+			GCDBG(GCZONE_ALLOC, "using storage buffer #%d.\n",
+				gcqueue->curstorageidx);
+
+			gcqueue->dirtystorage = false;
+		}
+
+		GCDBG(GCZONE_ALLOC, "queue logical = 0x%08X\n",
+		      (unsigned int) gcqueue->logical);
+		GCDBG(GCZONE_ALLOC, "queue physical = 0x%08X\n",
+		      gcqueue->physical);
+		GCDBG(GCZONE_ALLOC, "queue available = %d\n",
+			gcqueue->available);
+
+		/* Create a new command buffer entry if not created yet. */
+		if (list_empty(&gcqueue->cmdbufhead)) {
+			GCDBG(GCZONE_ALLOC, "allocating new queue entry.\n");
+
+			gcerror = gcqueue_alloc_cmdbuf(gcqueue, &gccmdbuf);
+			if (gcerror != GCERR_NONE)
+				goto exit;
+
+			list_add_tail(&gccmdbuf->link, &gcqueue->cmdbufhead);
+
+			gccmdbuf->gcmmucontext = gcmmucontext;
+			gccmdbuf->logical = gcqueue->logical;
+			gccmdbuf->physical = gcqueue->physical;
+			gccmdbuf->size = 0;
+			gccmdbuf->count = 0;
+			gccmdbuf->gcmoterminator = NULL;
+			gccmdbuf->interrupt = ~0U;
+		} else {
+			head = gcqueue->cmdbufhead.next;
+			gccmdbuf = list_entry(head, struct gccmdbuf, link);
+		}
+
+		/* Do we have enough room in the current buffer? */
+		if ((int) size <= gcqueue->available) {
+			/* Set the pointers. */
+			if (logical != NULL)
+				*logical = gcqueue->logical;
+
+			if (physical != NULL)
+				*physical = gcqueue->physical;
+
+			/* Update the info. */
+			gcqueue->logical += size;
+			gcqueue->physical += size;
+			gcqueue->available -= size;
+			gccmdbuf->size += size;
+
+			GCDBG_QUEUE(GCZONE_ALLOC, "updated ", gccmdbuf);
+			goto exit;
+		}
+
+		/* Execute the current command buffer. */
+		GCDBG_QUEUE(GCZONE_ALLOC, "current ", gccmdbuf);
+		GCDBG(GCZONE_ALLOC, "out of available space.\n");
+		gcerror = gcqueue_execute(gccorecontext, true, true);
+		if (gcerror != GCERR_NONE)
+			goto exit;
+	}
+
+exit:
+	GCEXITARG(GCZONE_ALLOC, "gc%s = 0x%08X\n",
+		(gcerror == GCERR_NONE) ? "result" : "error", gcerror);
+
+	return gcerror;
+}
+
+enum gcerror gcqueue_free(struct gccorecontext *gccorecontext,
+			  unsigned int size)
+{
+	struct list_head *head;
+	struct gcqueue *gcqueue;
+	struct gccmdbuf *gccmdbuf;
+
+	GCENTERARG(GCZONE_ALLOC, "context = 0x%08X, size = %d\n",
+		   (unsigned int) gccorecontext, size);
+
+	/* Get a shortcut to the queue object. */
+	gcqueue = &gccorecontext->gcqueue;
+
+	if (list_empty(&gcqueue->cmdbufhead)) {
+		GCERR("no current command buffer\n");
+	} else {
+		/* Get a pointer to the open entry. */
+		head = gcqueue->cmdbufhead.next;
+		gccmdbuf = list_entry(head, struct gccmdbuf, link);
+
+		/* Roll back the previous allocation. */
+		gcqueue->logical -= size;
+		gcqueue->physical -= size;
+		gcqueue->available += size;
+		gccmdbuf->size -= size;
+	}
+
+	GCEXIT(GCZONE_ALLOC);
+	return GCERR_NONE;
+}
+
+enum gcerror gcqueue_execute(struct gccorecontext *gccorecontext,
+			     bool switchtonext, bool asynchronous)
+{
+	enum gcerror gcerror = GCERR_NONE;
+	struct gcqueue *gcqueue;
+	struct gcmoterminator *gcmoterminator;
+	struct gcevent *gcevent;
+	struct gccmdbuf *gccmdbuf;
+	struct list_head *head;
+
+	GCENTERARG(GCZONE_EXEC, "context = 0x%08X, asynchronous = %d\n",
+		   (unsigned int) gccorecontext, asynchronous);
+
+	/* Get a shortcut to the queue object. */
+	gcqueue = &gccorecontext->gcqueue;
+
+	/* Nothing to execute? */
+	if (list_empty(&gcqueue->cmdbufhead))
+		goto exit;
+
+	/* Get the current command buffer. */
+	head = gcqueue->cmdbufhead.prev;
+	gccmdbuf = list_entry(head, struct gccmdbuf, link);
+
+	/* Determine the location of the terminator. */
+	gccmdbuf->gcmoterminator = gcmoterminator
+		= (struct gcmoterminator *) gcqueue->logical;
+
+	/* Configure the second entry as a wait. */
+	gcmoterminator->u2.wait.cmd.fld = gcfldwait200;
+
+	/* Configure the third entry as a link back to the wait. */
+	gcmoterminator->u3.linkwait.cmd.fld = gcfldlink2;
+	gcmoterminator->u3.linkwait.address = gcqueue->physical
+				+ offsetof(struct gcmoterminator, u2);
+
+	/* Update the info. */
+	gcqueue->logical += GC_TAIL_RESERVE;
+	gcqueue->physical += GC_TAIL_RESERVE;
+	gcqueue->available -= GC_TAIL_RESERVE;
+	gccmdbuf->size += GC_TAIL_RESERVE;
+
+	GCDBG(GCZONE_EXEC, "queue logical = 0x%08X\n",
+		(unsigned int) gcqueue->logical);
+	GCDBG(GCZONE_EXEC, "queue physical = 0x%08X\n",
+		gcqueue->physical);
+	GCDBG(GCZONE_EXEC, "queue available = %d\n",
+		gcqueue->available);
+
+	/* Determine data count. */
+	gccmdbuf->count = (gccmdbuf->size + 7) >> 3;
+
+	/* Is there an MMU flush in the buffer? */
+	if (gcqueue->flushlogical != NULL) {
+		GCDBG(GCZONE_EXEC, "finalizing MMU flush.\n");
+
+		/* Finalize the flush. */
+		gcmmu_flush_finalize(gccmdbuf,
+					gcqueue->flushlogical,
+					gcqueue->flushaddress);
+
+		/* Reset flush pointer. */
+		gcqueue->flushlogical = NULL;
+	}
+
+	GCDBG_QUEUE(GCZONE_EXEC, "current ", gccmdbuf);
+
+	/* Check the remaining space minimum threshold. */
+	if (switchtonext || (gcqueue->available < GC_MIN_THRESHOLD)) {
+		GCDBG(GCZONE_EXEC, "switching to the next storage.\n");
+
+		/* Add event for the current command buffer. */
+		gcerror = gcqueue_alloc_event(gcqueue, &gcevent);
+		if (gcerror != GCERR_NONE)
+			goto exit;
+
+		/* Initialize the event and add to the list. */
+		gcevent->handler = event_completion;
+		gcevent->event.completion.completion
+			= &gcqueue->curstorage->ready;
+		list_add_tail(&gcevent->link, &gccmdbuf->events);
+		GCDBG(GCZONE_EXEC, "buffer switch completion 0x%08X.\n",
+		      (unsigned int) gcevent->event.completion.completion);
+
+		/* Switch to the next storage buffer. */
+		gcqueue->curstorageidx = (gcqueue->curstorageidx + 1)
+					% GC_STORAGE_COUNT;
+		gcqueue->curstorage = &gcqueue->storagearray
+					[gcqueue->curstorageidx];
+
+		/* Initialize current allocation info. */
+		gcqueue->logical = (unsigned char *)
+				gcqueue->curstorage->page.logical;
+		gcqueue->physical = gcqueue->curstorage->physical;
+		gcqueue->available = gcqueue->curstorage->page.size
+					- GC_TAIL_RESERVE;
+
+		/* Invalidate the storage. */
+		gcqueue->dirtystorage = true;
+
+		GCDBG(GCZONE_EXEC, "switching to storage %d.\n",
+		      gcqueue->curstorageidx);
+	}
+
+	/* Add stall event for synchronous operation. */
+	if (!asynchronous) {
+		GCDBG(GCZONE_EXEC, "appending stall event.\n");
+
+		/* Add stall event. */
+		gcerror = gcqueue_alloc_event(gcqueue, &gcevent);
+		if (gcerror != GCERR_NONE)
+			goto exit;
+
+		/* Initialize the event and add to the list. */
+		gcevent->handler = event_completion;
+		gcevent->event.completion.completion = &gcqueue->stall;
+		list_add_tail(&gcevent->link, &gccmdbuf->events);
+		GCDBG(GCZONE_EXEC, "stall completion 0x%08X.\n",
+		      (unsigned int) gcevent->event.completion.completion);
+	}
+
+	/* If the buffer has no events, don't allocate an interrupt for it. */
+	if (list_empty(&gccmdbuf->events)) {
+		gcmoterminator->u1.nop.cmd.raw = gccmdnop_const.cmd.raw;
+	} else {
+		gcerror = gcqueue_alloc_int(gcqueue, &gccmdbuf->interrupt);
+		if (gcerror != GCERR_NONE)
+			goto exit;
+
+		gcmoterminator->u1.done.signal_ldst = gcmosignal_signal_ldst;
+		gcmoterminator->u1.done.signal.raw = 0;
+		gcmoterminator->u1.done.signal.reg.id = gccmdbuf->interrupt;
+		gcmoterminator->u1.done.signal.reg.pe
+						= GCREG_EVENT_PE_SRC_ENABLE;
+	}
+
+	/* Append the current command buffer to the queue. */
+	append_cmdbuf(gccorecontext, gcqueue);
+
+	/* Wait for completion. */
+	if (!asynchronous) {
+		GCDBG(GCZONE_EXEC, "waiting until execution is complete.\n");
+		GCWAIT_FOR_COMPLETION(&gcqueue->stall);
+		GCDBG(GCZONE_EXEC, "execution complete.\n");
+	}
+
+exit:
+	GCEXITARG(GCZONE_EXEC, "gc%s = 0x%08X\n",
+		(gcerror == GCERR_NONE) ? "result" : "error", gcerror);
+	return gcerror;
+}
+
+enum gcerror gcqueue_wait_idle(struct gccorecontext *gccorecontext)
+{
+	enum gcerror gcerror = GCERR_NONE;
+	struct gcqueue *gcqueue = &gccorecontext->gcqueue;
+	unsigned long timeout;
+	unsigned int count, limit;
+
+	GCENTER(GCZONE_THREAD);
+
+	/* Indicate shutdown immediately. */
+	gcqueue->suspend = true;
+	complete(&gcqueue->ready);
+
+	/* Convert timeout to jiffies. */
+	timeout = msecs_to_jiffies(GC_IDLE_TIMEOUT);
+
+	/* Compute the maximum number of attempts. */
+	limit = 5000 / GC_IDLE_TIMEOUT;
+
+	/* Wait for GPU to stop. */
+	count = 0;
+	while (gcqueue->suspend) {
+		wait_for_completion_timeout(&gcqueue->sleep, timeout);
+
+		/* Waiting too long? */
+		if (++count == limit) {
+			GCERR("wait for idle takes too long.\n");
+			gcerror = GCERR_TIMEOUT;
+			break;
+		}
+	}
+
+	GCEXIT(GCZONE_THREAD);
+	return gcerror;
+}
diff --git a/drivers/misc/gcx/gccore/gcqueue.h b/drivers/misc/gcx/gccore/gcqueue.h
new file mode 100644
index 0000000..5a37c1b
--- /dev/null
+++ b/drivers/misc/gcx/gccore/gcqueue.h
@@ -0,0 +1,231 @@
+/*
+ * gcqueue.h
+ *
+ * Copyright (C) 2010-2011 Vivante Corporation.
+ *
+ * This package is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#ifndef GCQUEUE_H
+#define GCQUEUE_H
+
+#include <linux/gccore.h>
+
+
+/*******************************************************************************
+ * Command queue defines.
+ */
+
+/* Number of the storage buffers that the driver will switch between. */
+#define GC_STORAGE_COUNT	2
+
+/* Number of command buffers that fit in one storage buffer. */
+#define GC_CMDBUF_FACTOR	2
+
+
+/*******************************************************************************
+ * Command queue structures.
+ */
+
+/* Execution control flags. */
+#define GC_CMDBUF_START_FE	(1 << 0)
+
+/* Event record. */
+struct gcevent {
+	/* Event handler function. */
+	void (*handler) (struct gcevent *gcevent, unsigned int *flags);
+
+	/* Event specific data. */
+	union {
+		struct {
+			struct completion *completion;
+		} completion;
+
+		struct {
+			void (*callback) (void *callbackparam);
+			void *callbackparam;
+		} callback;
+
+		struct {
+			struct gccorecontext *gccorecontext;
+			struct gcmmucontext *gcmmucontext;
+			struct gcmmuarena *gcmmuarena;
+		} unmap;
+	} event;
+
+	/* Previous/next event link. */
+	struct list_head link;
+};
+
+/* Command buffer storage descriptor. This represents a container within
+ * which smaller allocations are made, filled with commands and executed.
+ * There should be at least two of these storage buffers to allow for seamless
+ * execution. When there is no more room in the current storage buffer, the
+ * buffer is sent for execution while allocation can continue from the next
+ * storage buffer. */
+struct gccmdstorage {
+	/* Storage buffer allocation descriptor. */
+	struct gcpage page;
+
+	/* Physical (GPU mapped) address of the storage buffer. */
+	unsigned int physical;
+
+	/* Number of clients that have the storage buffer mapped.*/
+	unsigned int mapped;
+
+	/* Completion used for switching to this storage buffer. */
+	struct completion ready;
+};
+
+/* Command queue entry. */
+struct gccmdbuf {
+	/* Associated MMU context. */
+	struct gcmmucontext *gcmmucontext;
+
+	/* Pointers to the beginning of the command buffer and the size
+	 * of the command buffer in bytes. */
+	unsigned char *logical;
+	unsigned int physical;
+	unsigned int size;
+
+	/* The size of the command buffer in the number if 64-bit chunks. */
+	unsigned int count;
+
+	/* Command buffer terminator structure. */
+	struct gcmoterminator *gcmoterminator;
+
+	/* Interrupt number assigned to the command buffer. */
+	unsigned int interrupt;
+
+	/* Event list associated with the command buffer. */
+	struct list_head events;
+
+	/* Previous/next command queue entry. */
+	struct list_head link;
+};
+
+/* Command queue object. */
+struct gcqueue {
+	/* ISR installed flag. */
+	int isrroutine;
+
+	/* Storage buffer array. */
+	bool dirtystorage;
+	struct gccmdstorage storagearray[GC_STORAGE_COUNT];
+	struct gccmdstorage *curstorage;
+	unsigned int curstorageidx;
+
+	/* Pointers to the area of the current storage buffer available for
+	 * allocation and the size of the available space in bytes. */
+	unsigned char *logical;
+	unsigned int physical;
+	int available;
+
+	/* Array to keep track of which interrupts are in use. */
+	bool intused[30];
+	GCLOCK_TYPE intusedlock;
+
+	/* The completion to track the number of available interrupts. */
+	struct completion freeint;
+
+	/* Bit mask containing triggered interrupts. */
+	atomic_t triggered;
+
+	/* The tail of the last command buffer. */
+	struct gcmoterminator *gcmoterminator;
+
+	/* GPU running state. */
+	struct completion stopped;
+
+	/* Command buffer thread and thread control completions. */
+	struct task_struct *cmdthread;
+	struct completion ready;
+	struct completion stop;
+	struct completion sleep;
+
+	/* Suspend request flag. */
+	bool suspend;
+
+	/* Stall completion; used to imitate synchronous behaviour. */
+	struct completion stall;
+
+	/* Error signals. */
+	struct completion mmuerror;
+	struct completion buserror;
+
+	/* Command buffer currently being worked on. */
+	struct list_head cmdbufhead;
+
+	/* Queue of entries being executed (gccmdbuf). */
+	struct list_head queue;
+	GCLOCK_TYPE queuelock;
+
+	/* Cache of vacant event entries (gcevent). */
+	struct list_head vacevents;
+	GCLOCK_TYPE vaceventlock;
+
+	/* Cache of vacant queue entries (gccmdbuf). */
+	struct list_head vacqueue;
+	GCLOCK_TYPE vacqueuelock;
+
+	/* MMU flush pointers. */
+	struct gcmommuflush *flushlogical;
+	unsigned int flushaddress;
+};
+
+
+/*******************************************************************************
+ * Command queue management API.
+ */
+
+struct gccorecontext;
+struct gcmmucontext;
+
+enum gcerror gcqueue_start(struct gccorecontext *gccorecontext);
+enum gcerror gcqueue_stop(struct gccorecontext *gccorecontext);
+
+enum gcerror gcqueue_map(struct gccorecontext *gccorecontext,
+			 struct gcmmucontext *gcmmucontext);
+enum gcerror gcqueue_unmap(struct gccorecontext *gccorecontext,
+			   struct gcmmucontext *gcmmucontext);
+
+enum gcerror gcqueue_callback(struct gccorecontext *gccorecontext,
+			      struct gcmmucontext *gcmmucontext,
+			      void (*callback) (void *callbackparam),
+			      void *callbackparam);
+enum gcerror gcqueue_schedunmap(struct gccorecontext *gccorecontext,
+				struct gcmmucontext *gcmmucontext,
+				unsigned long handle);
+enum gcerror gcqueue_alloc(struct gccorecontext *gccorecontext,
+			   struct gcmmucontext *gcmmucontext,
+			   unsigned int size,
+			   void **logical,
+			   unsigned int *physical);
+enum gcerror gcqueue_free(struct gccorecontext *gccorecontext,
+			  unsigned int size);
+enum gcerror gcqueue_execute(struct gccorecontext *gccorecontext,
+			     bool switchtonext, bool asynchronous);
+
+enum gcerror gcqueue_alloc_event(struct gcqueue *gcqueue,
+				 struct gcevent **gcevent);
+enum gcerror gcqueue_free_event(struct gcqueue *gcqueue,
+				struct gcevent *gcevent);
+
+enum gcerror gcqueue_alloc_cmdbuf(struct gcqueue *gcqueue,
+				  struct gccmdbuf **gccmdbuf);
+void gcqueue_free_cmdbuf(struct gcqueue *gcqueue,
+			 struct gccmdbuf *gccmdbuf,
+			 unsigned int *flags);
+
+enum gcerror gcqueue_alloc_int(struct gcqueue *gcqueue,
+			       unsigned int *interrupt);
+
+enum gcerror gcqueue_wait_idle(struct gccorecontext *gccorecontext);
+
+#endif
diff --git a/drivers/misc/gcx/gcioctl/Kconfig b/drivers/misc/gcx/gcioctl/Kconfig
new file mode 100644
index 0000000..015abc9
--- /dev/null
+++ b/drivers/misc/gcx/gcioctl/Kconfig
@@ -0,0 +1,6 @@
+config GCIOCTL
+	tristate "User interface to Vivante 2D/3D driver"
+	default y
+	depends on GCCORE
+	help
+           User interface to Vivante 2D/3D driver.
diff --git a/drivers/misc/gcx/gcioctl/Makefile b/drivers/misc/gcx/gcioctl/Makefile
new file mode 100644
index 0000000..c04e01d
--- /dev/null
+++ b/drivers/misc/gcx/gcioctl/Makefile
@@ -0,0 +1,4 @@
+obj-$(CONFIG_GCIOCTL) += gcioctl.o
+
+gcioctl-y := \
+	gcif.o
diff --git a/drivers/misc/gcx/gcioctl/gcif.c b/drivers/misc/gcx/gcioctl/gcif.c
new file mode 100644
index 0000000..262522c
--- /dev/null
+++ b/drivers/misc/gcx/gcioctl/gcif.c
@@ -0,0 +1,1150 @@
+/*
+ * gcmain.c
+ *
+ * Copyright (C) 2010-2011 Vivante Corporation.
+ *
+ * This package is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/fs.h>
+#include <linux/device.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include <linux/uaccess.h>
+#include <linux/string.h>
+#include <plat/cpu.h>
+#include <linux/dma-mapping.h>
+#include <linux/platform_device.h>
+#include <linux/gcx.h>
+#include <linux/gccore.h>
+#include <linux/cache-2dmanager.h>
+#include "gcif.h"
+#include "version.h"
+
+#define GCZONE_NONE		0
+#define GCZONE_ALL		(~0U)
+#define GCZONE_INIT		(1 << 0)
+#define GCZONE_CAPS		(1 << 1)
+#define GCZONE_MAPPING		(1 << 2)
+#define GCZONE_CACHE		(1 << 3)
+#define GCZONE_COMMIT		(1 << 4)
+#define GCZONE_IOCTL		(1 << 5)
+#define GCZONE_CALLBACK		(1 << 6)
+
+GCDBG_FILTERDEF(ioctl, GCZONE_NONE,
+		"init",
+		"caps",
+		"mapping",
+		"cache",
+		"commit",
+		"ioctl",
+		"callback")
+
+static GCDEFINE_LOCK(g_fixuplock);
+static GCDEFINE_LOCK(g_bufferlock);
+static GCDEFINE_LOCK(g_unmaplock);
+
+static LIST_HEAD(g_buffervac);		/* gcbuffer */
+static LIST_HEAD(g_fixupvac);		/* gcfixup */
+static LIST_HEAD(g_unmapvac);		/* gcschedunmap */
+
+
+/*******************************************************************************
+ * Command buffer copy management.
+ */
+
+static enum gcerror alloc_fixup(struct gcfixup **gcfixup)
+{
+	enum gcerror gcerror = GCERR_NONE;
+	struct gcfixup *temp;
+
+	GCLOCK(&g_fixuplock);
+
+	if (list_empty(&g_fixupvac)) {
+		temp = kmalloc(sizeof(struct gcfixup), GFP_KERNEL);
+		if (temp == NULL) {
+			GCERR("out of memory.\n");
+			gcerror = GCERR_SETGRP(GCERR_OODM,
+					       GCERR_IOCTL_FIXUP_ALLOC);
+			goto exit;
+		}
+	} else {
+		struct list_head *head;
+		head = g_fixupvac.next;
+		temp = list_entry(head, struct gcfixup, link);
+		list_del(head);
+	}
+
+	GCUNLOCK(&g_fixuplock);
+
+	INIT_LIST_HEAD(&temp->link);
+	*gcfixup = temp;
+
+exit:
+	return gcerror;
+}
+
+static void free_fixup(struct gcfixup *gcfixup)
+{
+	GCLOCK(&g_fixuplock);
+	list_move(&gcfixup->link, &g_fixupvac);
+	GCUNLOCK(&g_fixuplock);
+}
+
+static void free_fixup_list(struct list_head *fixuplist)
+{
+	GCLOCK(&g_fixuplock);
+	list_splice_init(fixuplist, &g_fixupvac);
+	GCUNLOCK(&g_fixuplock);
+}
+
+static void free_vacant_fixups(void)
+{
+	struct list_head *head;
+	struct gcfixup *gcfixup;
+
+	GCLOCK(&g_fixuplock);
+	while (!list_empty(&g_fixupvac)) {
+		head = g_fixupvac.next;
+		gcfixup = list_entry(head, struct gcfixup, link);
+		list_del(head);
+		kfree(gcfixup);
+	}
+	GCUNLOCK(&g_fixuplock);
+}
+
+static enum gcerror alloc_buffer(struct gcbuffer **gcbuffer)
+{
+	enum gcerror gcerror = GCERR_NONE;
+	struct gcbuffer *temp;
+
+	GCLOCK(&g_bufferlock);
+
+	if (list_empty(&g_buffervac)) {
+		temp = kmalloc(sizeof(struct gcbuffer), GFP_KERNEL);
+		if (temp == NULL) {
+			GCERR("out of memory.\n");
+			gcerror = GCERR_SETGRP(GCERR_OODM,
+					       GCERR_IOCTL_BUF_ALLOC);
+			goto exit;
+		}
+	} else {
+		struct list_head *head;
+		head = g_buffervac.next;
+		temp = list_entry(head, struct gcbuffer, link);
+		list_del(head);
+	}
+
+	GCUNLOCK(&g_bufferlock);
+
+	INIT_LIST_HEAD(&temp->fixup);
+	INIT_LIST_HEAD(&temp->link);
+	*gcbuffer = temp;
+
+exit:
+	return gcerror;
+}
+
+static void free_buffer(struct gcbuffer *gcbuffer)
+{
+	/* Free fixups. */
+	free_fixup_list(&gcbuffer->fixup);
+
+	/* Free the buffer. */
+	GCLOCK(&g_bufferlock);
+	list_move(&gcbuffer->link, &g_buffervac);
+	GCUNLOCK(&g_bufferlock);
+}
+
+static void free_buffer_list(struct list_head *bufferlist)
+{
+	struct list_head *head;
+	struct gcbuffer *gcbuffer;
+
+	while (!list_empty(bufferlist)) {
+		head = bufferlist->next;
+		gcbuffer = list_entry(head, struct gcbuffer, link);
+		free_buffer(gcbuffer);
+	}
+}
+
+static void free_vacant_buffers(void)
+{
+	struct list_head *head;
+	struct gcbuffer *gcbuffer;
+
+	GCLOCK(&g_bufferlock);
+	while (!list_empty(&g_buffervac)) {
+		head = g_buffervac.next;
+		gcbuffer = list_entry(head, struct gcbuffer, link);
+		list_del(head);
+		kfree(gcbuffer);
+	}
+	GCUNLOCK(&g_bufferlock);
+}
+
+
+/*******************************************************************************
+ * Unmap list management.
+ */
+
+static enum gcerror alloc_schedunmap(struct gcschedunmap **gcschedunmap)
+{
+	enum gcerror gcerror = GCERR_NONE;
+	struct gcschedunmap *temp;
+
+	GCLOCK(&g_unmaplock);
+
+	if (list_empty(&g_unmapvac)) {
+		temp = kmalloc(sizeof(struct gcschedunmap), GFP_KERNEL);
+		if (temp == NULL) {
+			GCERR("out of memory.\n");
+			gcerror = GCERR_SETGRP(GCERR_OODM,
+					       GCERR_IOCTL_BUF_ALLOC);
+			goto exit;
+		}
+	} else {
+		struct list_head *head;
+		head = g_unmapvac.next;
+		temp = list_entry(head, struct gcschedunmap, link);
+		list_del(head);
+	}
+
+	GCUNLOCK(&g_unmaplock);
+
+	INIT_LIST_HEAD(&temp->link);
+	*gcschedunmap = temp;
+
+exit:
+	return gcerror;
+}
+
+static void free_schedunmap(struct gcschedunmap *gcschedunmap)
+{
+	GCLOCK(&g_unmaplock);
+	list_move(&gcschedunmap->link, &g_unmapvac);
+	GCUNLOCK(&g_unmaplock);
+}
+
+static void free_schedunmap_list(struct list_head *schedunmaplist)
+{
+	GCLOCK(&g_unmaplock);
+	list_splice_init(schedunmaplist, &g_unmapvac);
+	GCUNLOCK(&g_unmaplock);
+}
+
+static void free_vacant_unmap(void)
+{
+	struct list_head *head;
+	struct gcschedunmap *gcschedunmap;
+
+	GCLOCK(&g_unmaplock);
+	while (!list_empty(&g_unmapvac)) {
+		head = g_unmapvac.next;
+		gcschedunmap = list_entry(head, struct gcschedunmap, link);
+		list_del(head);
+		kfree(gcschedunmap);
+	}
+	GCUNLOCK(&g_unmaplock);
+}
+
+
+/*******************************************************************************
+ * Callback managemnent.
+ */
+
+/* Per-client callback handle. */
+struct gccallbackhandle {
+	/* Ready signal. */
+	struct completion ready;
+
+	/* List of triggered callbacks (gccallbackinfo). */
+	struct list_head triggered;
+
+	/* List of scheduled callbacks (gccallbackinfo). */
+	struct list_head scheduled;
+
+	/* Previous/next callback handle. */
+	struct list_head link;
+};
+
+/* Callback information. */
+struct gccallbackinfo {
+	/* Callback handle. */
+	unsigned long handle;
+
+	/* User callback. */
+	void (*callback) (void *callbackparam);
+	void *callbackparam;
+
+	/* Previous/next callback information. */
+	struct list_head link;
+};
+
+/* Callback lists. */
+static LIST_HEAD(g_handlelist);
+static LIST_HEAD(g_vachandle);
+static LIST_HEAD(g_vacinfo);
+static GCDEFINE_LOCK(g_callbacklock);
+
+static enum gcerror alloc_callbackhandle(struct gccallbackhandle **handle)
+{
+	enum gcerror gcerror;
+	struct gccallbackhandle *temp;
+
+	GCLOCK(&g_callbacklock);
+
+	if (list_empty(&g_vachandle)) {
+		temp = kmalloc(sizeof(struct gccallbackhandle), GFP_KERNEL);
+		if (temp == NULL) {
+			GCERR("failed to allocate callback handle.\n");
+			gcerror = GCERR_OODM;
+			goto exit;
+		}
+		list_add(&temp->link, &g_handlelist);
+	} else {
+		struct list_head *head;
+		head = g_vachandle.next;
+		temp = list_entry(head, struct gccallbackhandle, link);
+		list_move(head, &g_handlelist);
+	}
+
+	init_completion(&temp->ready);
+	INIT_LIST_HEAD(&temp->triggered);
+	INIT_LIST_HEAD(&temp->scheduled);
+
+	*handle = temp;
+	gcerror = GCERR_NONE;
+
+exit:
+	GCUNLOCK(&g_callbacklock);
+	return gcerror;
+}
+
+static void free_callbackhandle(struct gccallbackhandle *handle)
+{
+	GCLOCK(&g_callbacklock);
+	list_move(&handle->link, &g_vachandle);
+	GCUNLOCK(&g_callbacklock);
+}
+
+static enum gcerror alloc_callbackinfo(unsigned long handle,
+				       struct gccallbackinfo **info)
+{
+	enum gcerror gcerror;
+	struct gccallbackinfo *temp;
+	struct gccallbackhandle *gccallbackhandle;
+
+	GCLOCK(&g_callbacklock);
+
+	/* Get the callback handle. */
+	gccallbackhandle = (struct gccallbackhandle *) handle;
+
+	if (list_empty(&g_vacinfo)) {
+		temp = kmalloc(sizeof(struct gccallbackinfo), GFP_KERNEL);
+		if (temp == NULL) {
+			GCERR("failed to allocate callback info.\n");
+			gcerror = GCERR_OODM;
+			goto exit;
+		}
+		list_add_tail(&temp->link, &gccallbackhandle->scheduled);
+	} else {
+		struct list_head *head;
+		head = g_vacinfo.next;
+		temp = list_entry(head, struct gccallbackinfo, link);
+		list_move_tail(head, &gccallbackhandle->scheduled);
+	}
+
+	temp->handle = handle;
+
+	*info = temp;
+	gcerror = GCERR_NONE;
+
+exit:
+	GCUNLOCK(&g_callbacklock);
+	return gcerror;
+}
+
+static void gccallback(void *callbackparam)
+{
+	struct gccallbackinfo *gccallbackinfo;
+	struct gccallbackhandle *gccallbackhandle;
+
+	GCENTER(GCZONE_CALLBACK);
+
+	/* Cast callback info. */
+	gccallbackinfo = (struct gccallbackinfo *) callbackparam;
+	GCDBG(GCZONE_CALLBACK, "callback info received 0x%08X.\n",
+	      (unsigned int) gccallbackinfo);
+
+	/* Get the callback handle. */
+	gccallbackhandle = (struct gccallbackhandle *) gccallbackinfo->handle;
+	GCDBG(GCZONE_CALLBACK, "callback handle 0x%08X.\n",
+	      (unsigned int) gccallbackhandle);
+
+	/* Move to the triggered list. */
+	GCLOCK(&g_callbacklock);
+	list_move_tail(&gccallbackinfo->link, &gccallbackhandle->triggered);
+	GCUNLOCK(&g_callbacklock);
+
+	/* Complete ready signal. */
+	complete(&gccallbackhandle->ready);
+	GCDBG(GCZONE_CALLBACK, "user released.\n");
+
+	GCEXIT(GCZONE_CALLBACK);
+}
+
+static void destroy_callback(void)
+{
+	struct list_head *head;
+	struct gccallbackhandle *gccallbackhandle;
+	struct gccallbackinfo *gccallbackinfo;
+
+	while (!list_empty(&g_handlelist)) {
+		head = g_handlelist.next;
+		gccallbackhandle = list_entry(head,
+					      struct gccallbackhandle,
+					      link);
+
+		list_splice_init(&gccallbackhandle->triggered, &g_vacinfo);
+		list_splice_init(&gccallbackhandle->scheduled, &g_vacinfo);
+
+		list_del(head);
+		kfree(gccallbackhandle);
+	}
+
+	while (!list_empty(&g_vachandle)) {
+		head = g_vachandle.next;
+		gccallbackhandle = list_entry(head,
+					      struct gccallbackhandle,
+					      link);
+		list_del(head);
+		kfree(gccallbackhandle);
+	}
+
+	while (!list_empty(&g_vacinfo)) {
+		head = g_vacinfo.next;
+		gccallbackinfo = list_entry(head,
+					    struct gccallbackinfo,
+					    link);
+		list_del(head);
+		kfree(gccallbackinfo);
+	}
+}
+
+
+/*******************************************************************************
+ * API user wrappers.
+ */
+
+static int gc_getcaps_wrapper(struct gcicaps *gcicaps)
+{
+	int ret = 0;
+	struct gcicaps cpcaps;
+
+	GCENTER(GCZONE_CAPS);
+
+	/* Call the core driver. */
+	gc_caps(&cpcaps);
+
+	if (copy_to_user(gcicaps, &cpcaps, sizeof(struct gcicaps))) {
+		GCERR("failed to write data.\n");
+		ret = -EFAULT;
+	}
+
+	GCEXIT(GCZONE_CAPS);
+	return ret;
+}
+
+static int gc_commit_wrapper(struct gcicommit *gcicommit)
+{
+	int ret = 0;
+	bool buffercopied = false;
+	bool unmapcopied = false;
+	struct gcicommit cpcommit;
+	struct gccallbackinfo *gccallbackinfo;
+
+	struct list_head *gcbufferhead;
+	struct gcbuffer *cpbuffer, *gcbuffer;
+	LIST_HEAD(cpbufferlist);
+
+	struct list_head *gcfixuphead;
+	struct gcfixup *cpfixup, *gcfixup;
+	struct gcfixupentry *gcfixupentry;
+	int tablesize;
+
+	struct list_head *gcschedunmaphead;
+	struct gcschedunmap *cpschedunmap, *gcschedunmap;
+	LIST_HEAD(cpunmaplist);
+
+	GCENTER(GCZONE_COMMIT);
+
+	/* Get IOCTL parameters. */
+	if (copy_from_user(&cpcommit, gcicommit, sizeof(struct gcicommit))) {
+		GCERR("failed to read data.\n");
+		cpcommit.gcerror = GCERR_USER_READ;
+		goto exit;
+	}
+
+	/* Make a copy of the user buffer list. */
+	gcbufferhead = cpcommit.buffer.next;
+	while (gcbufferhead != &gcicommit->buffer) {
+		gcbuffer = list_entry(gcbufferhead, struct gcbuffer, link);
+		GCDBG(GCZONE_COMMIT, "copying buffer 0x%08X.\n",
+		      (unsigned int) gcbuffer);
+
+		/* Allocate a buffer structure. */
+		cpcommit.gcerror = alloc_buffer(&cpbuffer);
+		if (cpcommit.gcerror != GCERR_NONE)
+			goto exit;
+
+		/* Get the data from the user. */
+		if (copy_from_user(cpbuffer, gcbuffer,
+				   sizeof(struct gcbuffer))) {
+			free_buffer(cpbuffer);
+			GCERR("failed to read data.\n");
+			cpcommit.gcerror = GCERR_USER_READ;
+			goto exit;
+		}
+
+		/* Get the next user buffer. */
+		gcbufferhead = cpbuffer->link.next;
+
+		/* Add the buffer to the list. */
+		list_add_tail(&cpbuffer->link, &cpbufferlist);
+
+		/* Copy all fixups. */
+		gcfixuphead = cpbuffer->fixup.next;
+		INIT_LIST_HEAD(&cpbuffer->fixup);
+		while (gcfixuphead != &gcbuffer->fixup) {
+			gcfixup = list_entry(gcfixuphead, struct gcfixup, link);
+			GCDBG(GCZONE_COMMIT, "copying fixup 0x%08X.\n",
+			      (unsigned int) gcfixup);
+
+			/* Allocare a fixup structure. */
+			cpcommit.gcerror = alloc_fixup(&cpfixup);
+			if (cpcommit.gcerror != GCERR_NONE)
+				goto exit;
+
+			/* Get the size of the fixup array. */
+			if (copy_from_user(cpfixup, gcfixup,
+					   offsetof(struct gcfixup, fixup))) {
+				free_fixup(cpfixup);
+				GCERR("failed to read data.\n");
+				cpcommit.gcerror = GCERR_USER_READ;
+				goto exit;
+			}
+
+			/* Get the next fixup. */
+			gcfixuphead = cpfixup->link.next;
+
+			/* Add to the list. */
+			list_add_tail(&cpfixup->link, &cpbuffer->fixup);
+
+			/* Get the fixup array. */
+			gcfixupentry = gcfixup->fixup;
+
+			/* Compute the size of the fixup table. */
+			tablesize = cpfixup->count
+				  * sizeof(struct gcfixupentry);
+
+			/* Get the fixup table. */
+			if (copy_from_user(cpfixup->fixup, gcfixupentry,
+					   tablesize)) {
+				GCERR("failed to read data.\n");
+				cpcommit.gcerror = GCERR_USER_READ;
+				goto exit;
+			}
+		}
+	}
+
+	/* Move the local list to the commit structure. */
+	INIT_LIST_HEAD(&cpcommit.buffer);
+	list_splice_init(&cpbufferlist, &cpcommit.buffer);
+	buffercopied = true;
+
+	/* Copy scheduled unmappings to the local list. */
+	GCDBG(GCZONE_COMMIT, "copying unmaps.\n");
+	gcschedunmaphead = cpcommit.unmap.next;
+	while (gcschedunmaphead != &gcicommit->unmap) {
+		/* Get a pointer to the user structure. */
+		gcschedunmap = list_entry(gcschedunmaphead,
+					  struct gcschedunmap,
+					  link);
+		GCDBG(GCZONE_COMMIT, "unmap 0x%08X.\n",
+		      (unsigned int) gcschedunmap);
+
+		/* Allocate unmap record. */
+		cpcommit.gcerror = alloc_schedunmap(&cpschedunmap);
+		if (cpcommit.gcerror != GCERR_NONE)
+			goto exit;
+
+		/* Copy unmap record from user. */
+		if (copy_from_user(cpschedunmap, gcschedunmap,
+				   sizeof(struct gcschedunmap))) {
+			free_schedunmap(cpschedunmap);
+			GCERR("failed to read data.\n");
+			cpcommit.gcerror = GCERR_USER_READ;
+			goto exit;
+		}
+
+		/* Get the next record. */
+		gcschedunmaphead = cpschedunmap->link.next;
+
+		/* Append to the list. */
+		list_add_tail(&cpschedunmap->link, &cpunmaplist);
+	}
+
+	/* Move the local list to the commit structure. */
+	INIT_LIST_HEAD(&cpcommit.unmap);
+	list_splice_init(&cpunmaplist, &cpcommit.unmap);
+	unmapcopied = true;
+
+	/* Setup callback. */
+	if (cpcommit.callback != NULL) {
+		GCDBG(GCZONE_COMMIT, "setting up callback.\n");
+
+		/* Allocate callback info. */
+		cpcommit.gcerror = alloc_callbackinfo(cpcommit.handle,
+						      &gccallbackinfo);
+		if (cpcommit.gcerror != GCERR_NONE)
+			goto exit;
+
+		/* Initialize callback info. */
+		gccallbackinfo->callback = cpcommit.callback;
+		gccallbackinfo->callbackparam = cpcommit.callbackparam;
+
+		/* Substiture the callback. */
+		cpcommit.callback = gccallback;
+		cpcommit.callbackparam = gccallbackinfo;
+	} else {
+		GCDBG(GCZONE_COMMIT, "no callback provided.\n");
+	}
+
+	/* Call the core driver. */
+	gc_commit(&cpcommit, true);
+
+exit:
+	if (copy_to_user(&gcicommit->gcerror, &cpcommit.gcerror,
+			 sizeof(enum gcerror))) {
+		GCERR("failed to write data.\n");
+		ret = -EFAULT;
+	}
+
+	/* Free temporary resources. */
+	free_buffer_list(buffercopied ? &cpcommit.buffer : &cpbufferlist);
+	free_schedunmap_list(unmapcopied ? &cpcommit.unmap : &cpunmaplist);
+
+	GCEXIT(GCZONE_COMMIT);
+	return ret;
+}
+
+static int gc_map_wrapper(struct gcimap *gcimap)
+{
+	int ret = 0;
+	int mapped = 0;
+	struct gcimap cpmap;
+
+	GCENTER(GCZONE_MAPPING);
+
+	/* Get IOCTL parameters. */
+	if (copy_from_user(&cpmap, gcimap, sizeof(struct gcimap))) {
+		GCERR("failed to read data.\n");
+		cpmap.gcerror = GCERR_USER_READ;
+		goto exit;
+	}
+
+	cpmap.pagearray = NULL;
+
+	/* Call the core driver. */
+	gc_map(&cpmap, true);
+	if (cpmap.gcerror != GCERR_NONE)
+		goto exit;
+	mapped = 1;
+
+exit:
+	if (copy_to_user(gcimap, &cpmap, offsetof(struct gcimap, buf))) {
+		GCERR("failed to write data.\n");
+		cpmap.gcerror = GCERR_USER_WRITE;
+		ret = -EFAULT;
+	}
+
+	if (cpmap.gcerror != GCERR_NONE) {
+		if (mapped)
+			gc_unmap(&cpmap, true);
+	}
+
+	GCEXIT(GCZONE_MAPPING);
+	return ret;
+}
+
+static int gc_unmap_wrapper(struct gcimap *gcimap)
+{
+	int ret = 0;
+	struct gcimap cpmap;
+
+	GCENTER(GCZONE_MAPPING);
+
+	/* Get IOCTL parameters. */
+	if (copy_from_user(&cpmap, gcimap, sizeof(struct gcimap))) {
+		GCERR("failed to read data.\n");
+		cpmap.gcerror = GCERR_USER_READ;
+		goto exit;
+	}
+
+	/* Call the core driver. */
+	gc_unmap(&cpmap, true);
+
+exit:
+	if (copy_to_user(gcimap, &cpmap, offsetof(struct gcimap, buf))) {
+		GCERR("failed to write data.\n");
+		ret = -EFAULT;
+	}
+
+	GCEXIT(GCZONE_MAPPING);
+	return ret;
+}
+
+static int gc_cache_wrapper(struct gcicache *gcicache)
+{
+	int ret = 0;
+	struct gcicache cpcache;
+
+	GCENTER(GCZONE_CACHE);
+
+	/* Get IOCTL parameters. */
+	if (copy_from_user(&cpcache, gcicache, sizeof(struct gcicache))) {
+		GCERR("failed to read data.\n");
+		goto exit;
+	}
+
+	switch (cpcache.dir) {
+	case DMA_FROM_DEVICE:
+		c2dm_l2cache(cpcache.count, cpcache.rgn, cpcache.dir);
+		c2dm_l1cache(cpcache.count, cpcache.rgn, cpcache.dir);
+		break;
+
+	case DMA_TO_DEVICE:
+		c2dm_l1cache(cpcache.count, cpcache.rgn, cpcache.dir);
+		c2dm_l2cache(cpcache.count, cpcache.rgn, cpcache.dir);
+		break;
+
+	case DMA_BIDIRECTIONAL:
+		c2dm_l1cache(cpcache.count, cpcache.rgn, cpcache.dir);
+		c2dm_l2cache(cpcache.count, cpcache.rgn, cpcache.dir);
+		break;
+	}
+
+exit:
+	GCEXIT(GCZONE_CACHE);
+	return ret;
+}
+
+static int gc_callback_alloc(struct gcicallback *gcicallback)
+{
+	int ret = 0;
+	struct gcicallback cpcmdcallback;
+	struct gccallbackhandle *gccallbackhandle;
+
+	GCENTER(GCZONE_CALLBACK);
+
+	/* Reset the handle. */
+	cpcmdcallback.handle = 0;
+
+	/* Allocate callback handle struct. */
+	cpcmdcallback.gcerror = alloc_callbackhandle(&gccallbackhandle);
+	if (cpcmdcallback.gcerror != GCERR_NONE)
+		goto exit;
+
+	/* Set the handle. */
+	cpcmdcallback.handle = (unsigned long) gccallbackhandle;
+
+exit:
+	if (copy_to_user(gcicallback, &cpcmdcallback,
+			 sizeof(struct gcicallback))) {
+		GCERR("failed to write data.\n");
+		ret = -EFAULT;
+	}
+
+	GCEXIT(GCZONE_CALLBACK);
+	return ret;
+}
+
+static int gc_callback_free(struct gcicallback *gcicallback)
+{
+	int ret = 0;
+	struct gcicallback cpcmdcallback;
+	struct gccallbackhandle *gccallbackhandle;
+
+	GCENTER(GCZONE_CALLBACK);
+
+	/* Get IOCTL parameters. */
+	if (copy_from_user(&cpcmdcallback, gcicallback,
+			   sizeof(struct gcicallback))) {
+		GCERR("failed to read data.\n");
+		cpcmdcallback.gcerror = GCERR_USER_READ;
+		goto exit;
+	}
+
+	/* Free the handle struct. */
+	gccallbackhandle = (struct gccallbackhandle *) cpcmdcallback.handle;
+	free_callbackhandle(gccallbackhandle);
+
+	/* Reset the handle. */
+	cpcmdcallback.handle = 0;
+	cpcmdcallback.gcerror = GCERR_NONE;
+
+exit:
+	if (copy_to_user(gcicallback, &cpcmdcallback,
+			 sizeof(struct gcicallback))) {
+		GCERR("failed to write data.\n");
+		ret = -EFAULT;
+	}
+
+	GCEXIT(GCZONE_CALLBACK);
+	return ret;
+}
+
+static int gc_callback_wait(struct gcicallbackwait *gcicallbackwait)
+{
+	int ret = 0;
+	struct gcicallbackwait cpcmdcallbackwait;
+	struct gccallbackhandle *gccallbackhandle;
+	struct gccallbackinfo *gccallbackinfo;
+	struct list_head *head;
+	unsigned long timeout;
+
+	GCENTER(GCZONE_CALLBACK);
+
+	/* Get IOCTL parameters. */
+	if (copy_from_user(&cpcmdcallbackwait, gcicallbackwait,
+			   sizeof(struct gcicallbackwait))) {
+		GCERR("failed to read data.\n");
+		cpcmdcallbackwait.gcerror = GCERR_USER_READ;
+		goto exit;
+	}
+
+	/* Cast the handle. */
+	gccallbackhandle = (struct gccallbackhandle *) cpcmdcallbackwait.handle;
+
+	/* Convert milliseconds to jiffies. */
+	timeout = (cpcmdcallbackwait.timeoutms == ~0U)
+		? MAX_SCHEDULE_TIMEOUT
+		: msecs_to_jiffies(cpcmdcallbackwait.timeoutms);
+
+	/* Wait until a callback is triggered. */
+	timeout = wait_for_completion_interruptible_timeout(
+		&gccallbackhandle->ready, timeout);
+
+	if (timeout < 0) {
+		/* Error occurred. */
+		ret = timeout;
+	} else if (timeout == 0) {
+		/* Timeout. */
+		cpcmdcallbackwait.gcerror = GCERR_TIMEOUT;
+		cpcmdcallbackwait.callback = NULL;
+		cpcmdcallbackwait.callbackparam = NULL;
+	} else {
+		/* Callback event triggered. */
+		GCLOCK(&g_callbacklock);
+
+		if (list_empty(&gccallbackhandle->triggered)) {
+			GCERR("triggered list is empty.\n");
+		} else {
+			/* Get the head of the triggered list. */
+			head = gccallbackhandle->triggered.next;
+			gccallbackinfo = list_entry(head,
+						    struct gccallbackinfo,
+						    link);
+
+			/* Set callback info. */
+			cpcmdcallbackwait.callback
+				= gccallbackinfo->callback;
+			cpcmdcallbackwait.callbackparam
+				= gccallbackinfo->callbackparam;
+
+			/* Free the entry. */
+			list_move(head, &g_vacinfo);
+		}
+
+		GCUNLOCK(&g_callbacklock);
+		cpcmdcallbackwait.gcerror = GCERR_NONE;
+	}
+
+exit:
+	if (copy_to_user(gcicallbackwait, &cpcmdcallbackwait,
+			 sizeof(struct gcicallbackwait))) {
+		GCERR("failed to write data.\n");
+		ret = -EFAULT;
+	}
+
+	GCEXIT(GCZONE_CALLBACK);
+	return ret;
+}
+
+static int gc_callback_arm(struct gcicallbackarm *gcicallbackarm)
+{
+	int ret = 0;
+	struct gcicallbackarm cpcallbackarm;
+	struct gccallbackinfo *gccallbackinfo;
+
+	GCENTER(GCZONE_CALLBACK);
+
+	/* Get IOCTL parameters. */
+	if (copy_from_user(&cpcallbackarm, gcicallbackarm,
+			   sizeof(struct gcicallbackarm))) {
+		GCERR("failed to read data.\n");
+		cpcallbackarm.gcerror = GCERR_USER_READ;
+		goto exit;
+	}
+
+	/* Allocate callback info. */
+	cpcallbackarm.gcerror = alloc_callbackinfo(cpcallbackarm.handle,
+						   &gccallbackinfo);
+	if (cpcallbackarm.gcerror != GCERR_NONE)
+		goto exit;
+
+	/* Initialize callback info. */
+	gccallbackinfo->callback = cpcallbackarm.callback;
+	gccallbackinfo->callbackparam = cpcallbackarm.callbackparam;
+
+	/* Substiture the callback. */
+	cpcallbackarm.callback = gccallback;
+	cpcallbackarm.callbackparam = gccallbackinfo;
+
+	/* Call the core driver. */
+	gc_callback(&cpcallbackarm, true);
+
+exit:
+	if (copy_to_user(&gcicallbackarm->gcerror, &cpcallbackarm.gcerror,
+			 sizeof(enum gcerror))) {
+		GCERR("failed to write data.\n");
+		ret = -EFAULT;
+	}
+
+	GCEXIT(GCZONE_CALLBACK);
+	return ret;
+}
+
+
+/*******************************************************************************
+ * Device definitions/operations.
+ */
+
+static int dev_major;
+static struct class *dev_class;
+static struct device *dev_object;
+
+static int dev_open(struct inode *inode, struct file *file)
+{
+	if (cpu_is_omap447x())
+		return 0;
+	else
+		return -1;
+}
+
+static int dev_release(struct inode *inode, struct file *file)
+{
+	gc_release();
+	return 0;
+}
+
+static long dev_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+{
+	int ret;
+
+	switch (cmd) {
+	case GCIOCTL_GETCAPS:
+		GCDBG(GCZONE_IOCTL, "GCIOCTL_GETCAPS\n");
+		ret = gc_getcaps_wrapper((struct gcicaps *) arg);
+		break;
+
+	case GCIOCTL_COMMIT:
+		GCDBG(GCZONE_IOCTL, "GCIOCTL_COMMIT\n");
+		ret = gc_commit_wrapper((struct gcicommit *) arg);
+		break;
+
+	case GCIOCTL_MAP:
+		GCDBG(GCZONE_IOCTL, "GCIOCTL_MAP\n");
+		ret = gc_map_wrapper((struct gcimap *) arg);
+		break;
+
+	case GCIOCTL_UNMAP:
+		GCDBG(GCZONE_IOCTL, "GCIOCTL_UNMAP\n");
+		ret = gc_unmap_wrapper((struct gcimap *) arg);
+		break;
+
+	case GCIOCTL_CACHE:
+		GCDBG(GCZONE_IOCTL, "GCIOCTL_CACHE\n");
+		ret = gc_cache_wrapper((struct gcicache *) arg);
+		break;
+
+	case GCIOCTL_CALLBACK_ALLOC:
+		GCDBG(GCZONE_IOCTL, "GCIOCTL_CALLBACK_ALLOC\n");
+		ret = gc_callback_alloc((struct gcicallback *) arg);
+		break;
+
+	case GCIOCTL_CALLBACK_FREE:
+		GCDBG(GCZONE_IOCTL, "GCIOCTL_CALLBACK_FREE\n");
+		ret = gc_callback_free((struct gcicallback *) arg);
+		break;
+
+	case GCIOCTL_CALLBACK_WAIT:
+		GCDBG(GCZONE_IOCTL, "GCIOCTL_CALLBACK_WAIT\n");
+		ret = gc_callback_wait((struct gcicallbackwait *) arg);
+		break;
+
+	case GCIOCTL_CALLBACK_ARM:
+		GCDBG(GCZONE_IOCTL, "GCIOCTL_CALLBACK_ARM\n");
+		ret = gc_callback_arm((struct gcicallbackarm *) arg);
+		break;
+
+	default:
+		GCERR("invalid command (%d)\n", cmd);
+		ret = -EINVAL;
+	}
+
+	GCDBG(GCZONE_IOCTL, "ret = %d\n", ret);
+
+	return ret;
+}
+
+static const struct file_operations dev_operations = {
+	.open		= dev_open,
+	.release	= dev_release,
+	.unlocked_ioctl	= dev_ioctl,
+};
+
+
+/*******************************************************************************
+ * Device init/cleanup.
+ */
+
+static int mod_init(void);
+static void mod_exit(void);
+
+static struct platform_driver gcx_drv = {
+	.probe = 0,
+	.driver = {
+		.owner = THIS_MODULE,
+		.name = "gcx",
+	},
+};
+
+static const char *gcx_version = VER_FILEVERSION_STR;
+
+static ssize_t show_version(struct device_driver *driver, char *buf)
+{
+	return scnprintf(buf, PAGE_SIZE, "%s\n", gcx_version);
+}
+
+static DRIVER_ATTR(version, 0444, show_version, NULL);
+
+static int mod_init(void)
+{
+	int ret = 0;
+
+	GCDBG(GCZONE_INIT, "initializing device.\n");
+
+	/* Register the character device. */
+	dev_major = register_chrdev(0, GC_DEV_NAME, &dev_operations);
+	if (dev_major < 0) {
+		GCERR("failed to allocate device (%d).\n", ret = dev_major);
+		goto failed;
+	}
+
+	/* Create the device class. */
+	dev_class = class_create(THIS_MODULE, GC_DEV_NAME);
+	if (IS_ERR(dev_class)) {
+		GCERR("failed to create class (%d).\n",
+			ret = PTR_ERR(dev_class));
+		goto failed;
+	}
+
+	/* Create device. */
+	dev_object = device_create(dev_class, NULL, MKDEV(dev_major, 0),
+					NULL, GC_DEV_NAME);
+	if (IS_ERR(dev_object)) {
+		GCERR("failed to create device (%d).\n",
+			ret = PTR_ERR(dev_object));
+		goto failed;
+	}
+
+	ret = platform_driver_register(&gcx_drv);
+	if (ret) {
+		GCERR("failed to create gcx driver (%d).\n", ret);
+		goto failed;
+	}
+
+	ret = driver_create_file(&gcx_drv.driver, &driver_attr_version);
+	if (ret) {
+		GCERR("failed to create gcx driver version (%d).\n", ret);
+		goto failed;
+	}
+
+	GCDBG_REGISTER(ioctl, GCZONE_NONE);
+
+	GCDBG(GCZONE_INIT, "device number = %d\n", dev_major);
+	GCDBG(GCZONE_INIT, "device class = 0x%08X\n",
+		(unsigned int) dev_class);
+	GCDBG(GCZONE_INIT, "device object = 0x%08X\n",
+		(unsigned int) dev_object);
+
+	return 0;
+
+failed:
+	mod_exit();
+	return ret;
+}
+
+static void mod_exit(void)
+{
+	GCDBG(GCZONE_INIT, "cleaning up resources.\n");
+
+	if ((dev_object != NULL) && !IS_ERR(dev_object)) {
+		device_destroy(dev_class, MKDEV(dev_major, 0));
+		dev_object = NULL;
+	}
+
+	if ((dev_class != NULL) && !IS_ERR(dev_class)) {
+		class_destroy(dev_class);
+		dev_class = NULL;
+	}
+
+	if (dev_major > 0) {
+		unregister_chrdev(dev_major, GC_DEV_NAME);
+		dev_major = 0;
+	}
+
+	platform_driver_unregister(&gcx_drv);
+	driver_remove_file(&gcx_drv.driver, &driver_attr_version);
+
+	free_vacant_buffers();
+	free_vacant_fixups();
+	free_vacant_unmap();
+	destroy_callback();
+}
+
+static int __init mod_init_wrapper(void)
+{
+	return mod_init();
+}
+
+static void __exit mod_exit_wrapper(void)
+{
+	mod_exit();
+}
+
+MODULE_LICENSE("GPL v2");
+MODULE_AUTHOR("www.vivantecorp.com");
+MODULE_AUTHOR("www.ti.com");
+module_init(mod_init_wrapper);
+module_exit(mod_exit_wrapper);
diff --git a/drivers/misc/gcx/gcioctl/gcif.h b/drivers/misc/gcx/gcioctl/gcif.h
new file mode 100644
index 0000000..657b9f0
--- /dev/null
+++ b/drivers/misc/gcx/gcioctl/gcif.h
@@ -0,0 +1,20 @@
+/*
+ * gcmain.h
+ *
+ * Copyright (C) 2010-2011 Vivante Corporation.
+ *
+ * This package is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#ifndef GCMAIN_H
+#define GCMAIN_H
+
+#define GC_DEV_NAME	"gcioctl"
+
+#endif
diff --git a/drivers/misc/gcx/gcioctl/version.h b/drivers/misc/gcx/gcioctl/version.h
new file mode 100644
index 0000000..d32f32d
--- /dev/null
+++ b/drivers/misc/gcx/gcioctl/version.h
@@ -0,0 +1,4 @@
+#define VER_FILEVERSION             {2, 2, 2, 0}
+#define VER_FILEVERSION_STR         "2.2.2.0\0"
+#define VER_PRODUCTVERSION          {2, 2, 2, 0}
+#define VER_PRODUCTVERSION_STR      "2.2\0"
diff --git a/include/linux/gcbv-iface.h b/include/linux/gcbv-iface.h
new file mode 100644
index 0000000..6bb0ca4
--- /dev/null
+++ b/include/linux/gcbv-iface.h
@@ -0,0 +1,22 @@
+/*
+ * gcbv-iface.h
+ *
+ * Copyright (C) 2010-2011 Vivante Corporation.
+ *
+ * This package is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#ifndef GCBV_IFACE_H
+#define GCBV_IFACE_H
+
+#include "bltsville.h"
+
+void gcbv_init(struct bventry *entry);
+
+#endif
diff --git a/include/linux/gccore.h b/include/linux/gccore.h
new file mode 100644
index 0000000..ce9ed4f
--- /dev/null
+++ b/include/linux/gccore.h
@@ -0,0 +1,37 @@
+/*
+ * gccore.h
+ *
+ * Copyright (C) 2010-2011 Vivante Corporation.
+ *
+ * This package is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#ifndef GCCORE_H
+#define GCCORE_H
+
+#include "sched.h"
+#include "gcioctl.h"
+
+/* Capability query. */
+void gc_caps(struct gcicaps *gcicaps);
+
+/* Command buffer submission. */
+void gc_commit(struct gcicommit *gcicommit, bool fromuser);
+
+/* Client memory mapping. */
+void gc_map(struct gcimap *gcimap, bool fromuser);
+void gc_unmap(struct gcimap *gcimap, bool fromuser);
+
+/* Arm a callback. */
+void gc_callback(struct gcicallbackarm *gcicallbackarm, bool fromuser);
+
+/* Process cleanup. */
+void gc_release(void);
+
+#endif
diff --git a/include/linux/gcdbglog.h b/include/linux/gcdbglog.h
new file mode 100644
index 0000000..87022cd
--- /dev/null
+++ b/include/linux/gcdbglog.h
@@ -0,0 +1,412 @@
+/*
+ * gcdbglog.h
+ *
+ * Copyright (C) 2010-2011 Vivante Corporation.
+ *
+ * This package is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#ifndef GCDBGLOG_H
+#define GCDBGLOG_H
+
+#include "list.h"
+#include "bltsville.h"
+struct gcmmucontext;
+
+
+/*******************************************************************************
+ * Debug logging switches.
+ */
+
+/* Enables internal gccore logging backend. */
+#if !defined(GCDEBUG_ENABLE)
+#define GCDEBUG_ENABLE 1 /* enabled for development branch only */
+#endif
+
+/* Enables linux builtin logging backend. */
+#if !defined(GCDEBUG_LINUXLOGS)
+#define GCDEBUG_LINUXLOGS 0
+#endif
+
+#if GCDEBUG_ENABLE && GCDEBUG_LINUXLOGS
+#error GCDEBUG_ENABLE and GCDEBUG_LINUXLOGS cannot be enabled simultaneously.
+#endif
+
+
+/*******************************************************************************
+ * Dumping interface macro for release mode.
+ */
+
+#if !GCDEBUG_ENABLE && !GCDEBUG_LINUXLOGS
+#define GCDBG_INIT(...)
+#define GCDBG_EXIT(...)
+#define GCDBG_FILTERDEF(...)
+#define GCDBG_REGISTER(...)
+#define GCENTER(...)
+#define GCEXIT(...)
+#define GCENTERARG(...)
+#define GCEXITARG(...)
+#define GCDBG(...)
+#define GCERR(...)
+#define GCDUMPSTRING(...)
+#define GCDUMPBUFFER(...)
+#define GCDUMPARENA(...)
+#define GCDUMPARENAS(...)
+#define GCDUMPMMU(...)
+#endif
+
+#if !GCDEBUG_ENABLE
+#define GCDBG_REPORT_MISSING(file, line)				\
+	printk(KERN_INFO "(%s:%d) gcx logging is not integrated.\n",	\
+		   file, line)
+
+#define GCDBG_SHOWENABLED(s) \
+	GCDBG_REPORT_MISSING(__FILE__, __LINE__)
+
+#define GCDBG_ENABLEDUMP() \
+	GCDBG_REPORT_MISSING(__FILE__, __LINE__)
+
+#define GCDBG_DISABLEDUMP() \
+	GCDBG_REPORT_MISSING(__FILE__, __LINE__)
+
+#define GCDBG_SETFILTER(filtername, zone) \
+	GCDBG_REPORT_MISSING(__FILE__, __LINE__)
+
+#define GCDBG_FLUSHDUMP(s) \
+	GCDBG_REPORT_MISSING(__FILE__, __LINE__)
+
+#define GCDBG_RESETDUMP() \
+	GCDBG_REPORT_MISSING(__FILE__, __LINE__)
+
+#endif
+
+
+/*******************************************************************************
+ * Dumping macros not specific to a particular logging backend.
+ */
+
+#if GCDEBUG_ENABLE || GCDEBUG_LINUXLOGS
+
+#define GC_MOD_PREFIX \
+	GC_DEV_NAME ": %s(%d) "
+
+#define GCDUMPARENA(zone, text, arena) \
+do { \
+	GCDBG(zone, text " @ 0x%08X:\n", (unsigned int) arena); \
+	GCDBG(zone, "  number of pages = %u\n", \
+		(arena)->count); \
+	GCDBG(zone, "  from (absolute/mtlb/stlb) = 0x%08X / %u / %u\n", \
+		(arena)->start.absolute, \
+		(arena)->start.loc.mtlb, \
+		(arena)->start.loc.stlb); \
+	GCDBG(zone, "  to   (absolute/mtlb/stlb) = 0x%08X / %u / %u\n", \
+		(arena)->end.absolute, \
+		(arena)->end.loc.mtlb, \
+		(arena)->end.loc.stlb); \
+} while (false)
+
+#define GCDUMPARENAS(zone, text, arenahead) \
+do { \
+	GCDBG(zone, "%s:\n", text); \
+	\
+	if (list_empty(arenahead)) { \
+		GCDBG(zone, "  no arenas defined in the list.\n"); \
+	} else { \
+		struct list_head *entry; \
+		struct gcmmuarena *arena; \
+		\
+		list_for_each(entry, arenahead) { \
+			arena = list_entry(entry, struct gcmmuarena, link); \
+			GCDUMPARENA(zone, "arena", arena); \
+		} \
+	} \
+} while (false)
+
+#endif
+
+#define GC_FUNC_ENTER "++"
+#define GC_FUNC_EXIT "--"
+
+
+/*******************************************************************************
+ * Dumping macros for internal gccore logging backend.
+ */
+
+#if GCDEBUG_ENABLE
+
+#define GCDBGFILTER \
+	g_gcdbgfilter
+
+#define GCDBG_INIT() \
+	gcdbg_init()
+
+#define GCDBG_EXIT() \
+	gcdbg_exit()
+
+#define GCDBG_FILTERDEF(name, initzone, ...) \
+	static struct gcdbgfilter GCDBGFILTER = { \
+		.link = LIST_HEAD_INIT(GCDBGFILTER.link), \
+		.filtername = #name, \
+		.zone = initzone, \
+		.zonename = { __VA_ARGS__, NULL } \
+	}; \
+	\
+	struct gcdbgfilter *name ## _dbgfilter(void) \
+	{ \
+		return &GCDBGFILTER; \
+	}
+
+#define GCDBG_REGISTER(name, initalzone) \
+do { \
+	struct gcdbgfilter *name ## _dbgfilter(void); \
+	name ## _dbgfilter()->zone = initalzone; \
+	gc_dbg_add_client(name ## _dbgfilter()); \
+} while (0)
+
+#define GCDBG_SHOWENABLED(s) \
+	gc_dump_show_enabled(s)
+
+#define GCDBG_ENABLEDUMP() \
+	gc_dump_enable()
+
+#define GCDBG_DISABLEDUMP() \
+	gc_dump_disable()
+
+#define GCDBG_SETFILTER(filtername, zone) \
+	gc_dump_filter_enable(filtername, zone)
+
+#define GCDBG_FLUSHDUMP(s) \
+	gc_dump_flush(s)
+
+#define GCDBG_RESETDUMP() \
+	gc_dump_reset()
+
+#define GCENTER(zone) \
+	gc_dump_string(&GCDBGFILTER, zone, GC_FUNC_ENTER GC_MOD_PREFIX "\n", \
+			__func__, __LINE__)
+
+#define GCEXIT(zone) \
+	gc_dump_string(&GCDBGFILTER, zone, GC_FUNC_EXIT GC_MOD_PREFIX "\n", \
+			__func__, __LINE__)
+
+#define GCENTERARG(zone, msg, ...) \
+	gc_dump_string(&GCDBGFILTER, zone, GC_FUNC_ENTER GC_MOD_PREFIX msg, \
+			__func__, __LINE__, ##__VA_ARGS__)
+
+#define GCEXITARG(zone, msg, ...) \
+	gc_dump_string(&GCDBGFILTER, zone, GC_FUNC_EXIT GC_MOD_PREFIX msg, \
+			__func__, __LINE__, ##__VA_ARGS__)
+
+#define GCDBG(zone, msg, ...) \
+	gc_dump_string(&GCDBGFILTER, zone, GC_MOD_PREFIX msg,	\
+			__func__, __LINE__, ##__VA_ARGS__)
+
+#define GCERR(msg, ...) \
+	gc_dump_string(NULL, 0, GC_MOD_PREFIX "[ERROR] " msg,	\
+			__func__, __LINE__, ##__VA_ARGS__)
+
+#define GCDUMPSTRING(msg, ...) \
+	gc_dump_string(NULL, 0, msg, ##__VA_ARGS__)
+
+#define GCDUMPBUFFER(zone, ptr, gpuaddr, datasize) \
+	gc_dump_cmd_buffer(&GCDBGFILTER, zone, ptr, gpuaddr, datasize)
+
+#define GCDUMPMMU(zone, gcmmucontext) \
+	gc_dump_mmu(&GCDBGFILTER, zone, gcmmucontext)
+
+#endif
+
+
+/*******************************************************************************
+ * Dumping macros for linux builtin logging backend.
+ */
+
+#if GCDEBUG_LINUXLOGS
+
+#define GCDBG_INIT()
+#define GCDBG_EXIT()
+#define GCDBG_FILTERDEF(...)
+#define GCDBG_REGISTER(...)
+
+#define GCENTER(zone) \
+	GCDBG(zone, GC_FUNC_ENTER " %s(%d)\n", __func__, __LINE__)
+
+#define GCEXIT(zone) \
+	GCDBG(zone, GC_FUNC_EXIT " %s(%d)\n", __func__, __LINE__)
+
+#define GCENTERARG(zone, msg, ...) \
+	GCDBG(zone, GC_FUNC_ENTER " %s(%d) " msg "\n", \
+	      __func__, __LINE__, ##__VA_ARGS__)
+
+#define GCEXITARG(zone, msg, ...) \
+	GCDBG(zone, GC_FUNC_EXIT " %s(%d) " msg "\n", \
+	      __func__, __LINE__, ##__VA_ARGS__)
+
+#define GCDBG(zone, msg, ...) \
+	dev_dbg(gc_get_dev(), msg, ##__VA_ARGS__)
+
+#define GCERR(msg, ...) \
+	GCDBG(0, msg, ##__VA_ARGS__)
+
+#define GCDUMPSTRING(msg, ...) \
+	GCDBG(0, msg, ##__VA_ARGS__)
+
+#define GCDUMPBUFFER(...)
+
+#endif
+
+
+/*******************************************************************************
+ * Command buffer parser.
+ */
+
+struct gcsurfaceinfo {
+	unsigned int width;
+	unsigned int height;
+	unsigned int address;
+	unsigned int stride;
+	unsigned int swizzle;
+	unsigned int format;
+	unsigned int bpp;
+};
+
+struct gcrect {
+	int left;
+	int top;
+	int right;
+	int bottom;
+};
+
+struct gcsourceinfo {
+	struct gcsurfaceinfo surf;
+	struct gcrect rect;
+};
+
+struct gcdestinfo {
+	struct gcsurfaceinfo surf;
+	unsigned int rectcount;
+	struct gcrect rect[256];
+};
+
+struct gccommandinfo {
+	unsigned int command;
+	unsigned int srccount;
+	struct gcsourceinfo src[4];
+	struct gcdestinfo dst;
+};
+
+/* Parse the specified command buffer and fill in the structure. */
+int gc_parse_command_buffer(unsigned int *buffer, unsigned int size,
+			    struct gccommandinfo *info);
+
+
+/*******************************************************************************
+ * Filter structure.
+ */
+
+struct gcdbgfilter {
+	struct list_head link;
+	char *filtername;
+	unsigned int zone;
+	const char *zonename[];
+};
+
+
+/*******************************************************************************
+ * Debug init/exit functions.
+ */
+
+void gcdbg_init(void);
+void gcdbg_exit(void);
+
+
+/*******************************************************************************
+ * Dumping functions.
+ */
+
+/* Print GPU status. */
+void gc_dump_status(struct gcdbgfilter *filter, unsigned int zone,
+		    char *function, int line);
+
+/* String dumping. */
+void gc_dump_string(struct gcdbgfilter *filter, unsigned int zone,
+		    const char *message, ...);
+void gc_dump_string_sized(struct gcdbgfilter *filter, unsigned int zone,
+			  unsigned int argsize, const char *message, ...);
+
+/* Dump command buffer. */
+void gc_dump_cmd_buffer(struct gcdbgfilter *filter, unsigned int zone,
+			void *ptr, unsigned int gpuaddr, unsigned int datasize);
+
+/* Dump generic buffer. */
+void gc_dump_buffer(struct gcdbgfilter *filter, unsigned int zone,
+		    void *ptr, unsigned int gpuaddr, unsigned int datasize);
+void gc_dump_phys_buffer(struct gcdbgfilter *filter, unsigned int zone,
+			 struct gcmmucontext *gcmmucontext,
+			 unsigned int gpuaddr, unsigned int datasize);
+
+/* Dump surface. */
+void gc_dump_surface(struct gcdbgfilter *filter, unsigned int zone,
+		     void *ptr, unsigned int surfwidth,
+		     unsigned int surfheight, unsigned int surfbpp,
+		     unsigned int x1, unsigned int y1,
+		     unsigned int x2, unsigned int y2,
+		     unsigned int gpuaddr);
+void gc_dump_phys_surface(struct gcdbgfilter *filter, unsigned int zone,
+			  struct gcmmucontext *gcmmucontext,
+			  unsigned int surfwidth, unsigned int surfheight,
+			  unsigned int surfbpp,
+			  unsigned int x1, unsigned int y1,
+			  unsigned int x2, unsigned int y2,
+			  unsigned int gpuaddr);
+
+/* Dump MMU content. */
+void gc_dump_mmu(struct gcdbgfilter *filter, unsigned int zone,
+		 struct gcmmucontext *gcmmucontext);
+
+
+/*******************************************************************************
+ * CPU blitters.
+ */
+
+/* Fill surface using its virtual GPU address. */
+void gc_fill_phys_surface(struct gcdbgfilter *filter, unsigned int zone,
+			  struct gcmmucontext *gcmmucontext,
+			  unsigned int surfwidth,
+			  unsigned int surfheight,
+			  unsigned int surfbpp,
+			  unsigned int x1, unsigned int y1,
+			  unsigned int x2, unsigned int y2,
+			  unsigned int gpuaddr,
+			  unsigned int fillcolor);
+
+
+/*******************************************************************************
+ * Bltsville debugging.
+ */
+
+char *gc_bvblend_name(enum bvblend blend);
+
+
+/*******************************************************************************
+ * Dumping control.
+ */
+
+struct seq_file;
+
+struct device *gc_get_dev(void);
+void gc_dump_show_enabled(struct seq_file *s);
+void gc_dump_enable(void);
+void gc_dump_disable(void);
+void gc_dump_filter_enable(const char *filtername, int zone);
+void gc_dump_flush(struct seq_file *s);
+void gc_dump_reset(void);
+void gc_dbg_add_client(struct gcdbgfilter *filter);
+
+#endif
diff --git a/include/linux/gcdebug.h b/include/linux/gcdebug.h
new file mode 100644
index 0000000..8cbc0a4
--- /dev/null
+++ b/include/linux/gcdebug.h
@@ -0,0 +1,28 @@
+/*
+ * gcdebug.h
+ *
+ * Copyright (C) 2010-2011 Vivante Corporation.
+ *
+ * This package is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#ifndef GCDEBUG_H
+#define GCDEBUG_H
+
+#define GCGPUSTATUS() \
+	gc_debug_dump_status(__func__, __LINE__)
+
+void gc_debug_init(void);
+void gc_debug_shutdown(void);
+
+void gc_debug_poweroff_cache(void);
+void gc_debug_cache_gpu_status_from_irq(unsigned int acknowledge);
+void gc_debug_dump_status(const char *function, int line);
+
+#endif
diff --git a/include/linux/gcerror.h b/include/linux/gcerror.h
new file mode 100644
index 0000000..7939206
--- /dev/null
+++ b/include/linux/gcerror.h
@@ -0,0 +1,208 @@
+/*
+ * gcerror.h
+ *
+ * Copyright (C) 2010-2011 Vivante Corporation.
+ *
+ * This package is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#ifndef GCERROR_H
+#define GCERROR_H
+
+#define GCERR_SETGRP(error, group) \
+( \
+	(enum gcerror) \
+	((error & GCERR_GENERIC_MASK) | group) \
+)
+
+#define GCERR_GENERIC(error) \
+( \
+	(error & GCERR_GENERIC_MASK) << GCERR_GENERIC_SHIFT \
+)
+
+#define GCERR_GROUP(error) \
+( \
+	(error & GCERR_GROUP_MASK) << GCERR_GROUP_SHIFT \
+)
+
+enum gcerror {
+	/***********************************************************************
+	** No error / success.
+	*/
+	GCERR_NONE = 0,
+
+	/***********************************************************************
+	** Error code zones.
+	*/
+
+	/* Generic error code zone. These errors inform of the low level
+	   reason of the faulure, but don't carry information about which
+	   logical part of the code generated the error. */
+	GCERR_GENERIC_SIZE = 12,
+	GCERR_GENERIC_SHIFT = 0,
+	GCERR_GENERIC_MASK
+		= ((1 << GCERR_GENERIC_SIZE) - 1) << GCERR_GENERIC_SHIFT,
+
+	/* Group error code zone. These errors inform about the logical part
+	   of the code where the error occurred. */
+	GCERR_GROUP_SIZE = (32 - GCERR_GENERIC_SIZE),
+	GCERR_GROUP_SHIFT = GCERR_GENERIC_SIZE,
+	GCERR_GROUP_MASK
+		= ((1 << GCERR_GROUP_SIZE) - 1) << GCERR_GROUP_SHIFT,
+
+	/***********************************************************************
+	** Generic zone errors.
+	*/
+
+	GCERR_OODM			/* Out of dynamic memory. */
+	= GCERR_GENERIC(1),
+
+	GCERR_OOPM			/* Out of paged memory. */
+	= GCERR_GENERIC(2),
+
+	GCERR_PMMAP			/* Paged memory mapping. */
+	= GCERR_GENERIC(3),
+
+	GCERR_USER_READ			/* Reading user input. */
+	= GCERR_GENERIC(4),
+
+	GCERR_USER_WRITE		/* Writing user output. */
+	= GCERR_GENERIC(5),
+
+	GCERR_INTERRUPTED		/* Interrupted by a signal. */
+	= GCERR_GENERIC(6),
+
+	GCERR_TIMEOUT			/* Timeout. */
+	= GCERR_GENERIC(7),
+
+	GCERR_NOT_FOUND			/* Data/entry not found. */
+	= GCERR_GENERIC(8),
+
+	GCERR_IOCTL			/* IOCTL failed. */
+	= GCERR_GENERIC(9),
+
+	/***********************************************************************
+	** Group zone errors.
+	*/
+
+	/**** Context errors. */
+	GCERR_CTX_ALLOC			/* Context allocation. */
+	= GCERR_GROUP(0x01000),
+
+	GCERR_CTX_CHANGE		/* Lock/unlock error. */
+	= GCERR_GROUP(0x01010),
+
+	GCERR_CTX_NULL			/* Context not set. */
+	= GCERR_GROUP(0x01020),
+
+	/**** Command queue errors. */
+	GCERR_CMD_ENTRY_PIPE		/* Entry pipe is invalid. */
+	= GCERR_GROUP(0x02000),
+
+	GCERR_CMD_EXIT_PIPE		/* Exit pipe is invalid. */
+	= GCERR_GROUP(0x02010),
+
+	GCERR_CMD_MAPPED		/* Command buffer mapping error. */
+	= GCERR_GROUP(0x02020),
+
+	GCERR_CMD_CONSISTENCY		/* Inconsistent mapping. */
+	= GCERR_GROUP(0x02030),
+
+	GCERR_CMD_ALLOC			/* Buffer allocation. */
+	= GCERR_GROUP(0x02040),
+
+	GCERR_CMD_QUEUE_ALLOC		/* Buffer queue allocation. */
+	= GCERR_GROUP(0x02050),
+
+	GCERR_CMD_EVENT_ALLOC		/* Event allocation. */
+	= GCERR_GROUP(0x02060),
+
+	GCERR_CMD_INT_ALLOC		/* Interrupt allocation. */
+	= GCERR_GROUP(0x02070),
+
+	GCERR_CMD_ISR			/* ISR initialization. */
+	= GCERR_GROUP(0x02080),
+
+	GCERR_CMD_THREAD		/* Thread initialization. */
+	= GCERR_GROUP(0x02090),
+
+	/**** MMU errors. */
+	GCERR_MMU_CTXT_BAD		/* Invalid context. */
+	= GCERR_GROUP(0x03000),
+
+	GCERR_MMU_MTLB_ALLOC		/* MTLB allocation. */
+	= GCERR_GROUP(0x03010),
+
+	GCERR_MMU_MTLB_SET		/* MTLB setting. */
+	= GCERR_GROUP(0x03020),
+
+	GCERR_MMU_STLB_ALLOC		/* STLB allocation. */
+	= GCERR_GROUP(0x03030),
+
+	GCERR_MMU_STLBIDX_ALLOC		/* STLB index allocation. */
+	= GCERR_GROUP(0x03040),
+
+	GCERR_MMU_ARENA_ALLOC		/* Vacant arena allocation. */
+	= GCERR_GROUP(0x03050),
+
+	GCERR_MMU_OOM			/* No available arenas to allocate. */
+	= GCERR_GROUP(0x03060),
+
+	GCERR_MMU_SAFE_ALLOC		/* Safe zone allocation. */
+	= GCERR_GROUP(0x03070),
+
+	GCERR_MMU_INIT			/* MMU initialization. */
+	= GCERR_GROUP(0x03080),
+
+	GCERR_MMU_ARG			/* Invalid argument. */
+	= GCERR_GROUP(0x03090),
+
+	GCERR_MMU_CLIENT		/* Client initialization. */
+	= GCERR_GROUP(0x030A0),
+
+	GCERR_MMU_BUFFER_BAD		/* Invalid buffer to map. */
+	= GCERR_GROUP(0x030B0),
+
+	GCERR_MMU_PAGE_BAD		/* Bad page within the buffer. */
+	= GCERR_GROUP(0x030C0),
+
+	GCERR_MMU_DESC_ALLOC		/* Bad page within the buffer. */
+	= GCERR_GROUP(0x030D0),
+
+	GCERR_MMU_PHYS_ALLOC		/* Bad page within the buffer. */
+	= GCERR_GROUP(0x030E0),
+
+	GCERR_MMU_OFFSET		/* Bad buffer offset. */
+	= GCERR_GROUP(0x030F0),
+
+	/**** Power management. */
+	GCERR_POWER_MODE		/* Invlalid power mode requested. */
+	= GCERR_GROUP(0x04000),
+
+	GCERR_POWER_CLOCK_ON		/* Failed to enable clock. */
+	= GCERR_GROUP(0x04010),
+
+	GCERR_POWER_IRQ_ON		/* Failed to install IRQ handler. */
+	= GCERR_GROUP(0x04020),
+
+	GCERR_POWER_PULSE		/* Pulse skipping error. */
+	= GCERR_GROUP(0x04030),
+
+	/**** GCIOCTL module errors. */
+	GCERR_IOCTL_CTX_ALLOC		/* Context wrapper allocation. */
+	= GCERR_GROUP(0x11000),
+
+	GCERR_IOCTL_BUF_ALLOC		/* Command buffer allocation. */
+	= GCERR_GROUP(0x11010),
+
+	GCERR_IOCTL_FIXUP_ALLOC		/* Fixup buffer allocation. */
+	= GCERR_GROUP(0x11020),
+};
+
+#endif
diff --git a/include/linux/gcioctl.h b/include/linux/gcioctl.h
new file mode 100644
index 0000000..c89ddd8
--- /dev/null
+++ b/include/linux/gcioctl.h
@@ -0,0 +1,275 @@
+/*
+ * gcioctl.h
+ *
+ * Copyright (C) 2010-2011 Vivante Corporation.
+ *
+ * This package is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#ifndef GCIOCTL_H
+#define GCIOCTL_H
+
+#include "list.h"
+#include "gcerror.h"
+#include "gcreg.h"
+#include "cache-2dmanager.h"
+#include "bverror.h"
+
+/* IOCTL parameters. */
+#define GCIOCTL_TYPE 0x5D
+#define GCIOCTL_BASE 0x5D
+
+
+/*******************************************************************************
+ * Capability query API entry.
+ */
+
+#define GCIOCTL_GETCAPS _IOWR(GCIOCTL_TYPE, GCIOCTL_BASE + 0x00, \
+			      struct gcicaps)
+
+/* GCIOCTL_CALLBACK_ALLOC / GCIOCTL_CALLBACK_FREE:
+ *   To be able to use the callback mechanism each user space client must
+ *   use the ALLOC/FREE APIs to manage a kernel side callback object
+ *   represented by the handle member of struct gcicallback.
+ *   ALLOC API allocates the object and returns the handle to it. */
+struct gcicaps {
+	/* Error code. */
+	enum gcerror gcerror;
+
+	/* Capabilities and characteristics. */
+	unsigned int gcmodel;
+	unsigned int gcrevision;
+	unsigned int gcdate;
+	unsigned int gctime;
+	union gcfeatures gcfeatures;
+	union gcfeatures0 gcfeatures0;
+	union gcfeatures1 gcfeatures1;
+	union gcfeatures2 gcfeatures2;
+	union gcfeatures3 gcfeatures3;
+};
+
+/*******************************************************************************
+ * Commit API entry.
+ */
+
+#define GCIOCTL_COMMIT _IOWR(GCIOCTL_TYPE, GCIOCTL_BASE + 0x10, \
+			     struct gcicommit)
+
+/* GPU graphics pipe definition. */
+enum gcpipe {
+	GCPIPE_UNKNOWN,
+	GCPIPE_2D,
+	GCPIPE_3D
+};
+
+/* Commit header; contains pointers to the head and the tail of a linked list
+   of command buffers to execute. */
+struct gcicommit {
+	/* Return status code. */
+	enum gcerror gcerror;
+
+	/* Entry graphics pipe specifies the pipe the GPU is expected to be in
+	 * for successfull execution of the specified command buffers in this
+	 * call. Exit graphics pipe specifies the state of the GPU after the
+	 * buffers are executed. */
+	enum gcpipe entrypipe;
+	enum gcpipe exitpipe;
+
+	/* List of command buffers to be executed (gcbuffer). */
+	struct list_head buffer;
+
+	/* Pointer to the callback function to be called when the GPU completes
+	 * execution of all buffers specified in this call. This member can be
+	 * NULL if no callback is desired. callbackparam specifies data to be
+	 * passed to the callback. */
+	void (*callback) (void *callbackparam);
+	void *callbackparam;
+
+	/* Callback object handle allocated with GCIOCTL_CALLBACK_ALLOC API. */
+	unsigned long handle;
+
+	/* If asynchronous is set to true, the call returns immediately without
+	 * waiting until all specified buffers have been executed. If set to
+	 * false, the call does not return until execution is finished. */
+	bool asynchronous;
+
+	/* Scheduled unmappings (gcschedunmap). */
+	struct list_head unmap;
+};
+
+/* Command buffer header. */
+#define GC_BUFFER_SIZE (32 * 1024)
+struct gcbuffer {
+	/* Fixup list (gcfixup). */
+	struct list_head fixup;
+
+	/* Number of pixels to be rendered. */
+	unsigned int pixelcount;
+
+	/* Pointers to the head and tail of the command buffer list. */
+	unsigned int *head;
+	unsigned int *tail;
+
+	/* Number of bytes available in the buffer for allocation. */
+	unsigned int available;
+
+	/* Commmand buffer list (gcbuffer). */
+	struct list_head link;
+};
+
+/* Fixup entry. */
+struct gcfixupentry {
+	/* Offset into the commmand buffer where fixup is to be performed. */
+	unsigned int dataoffset;
+
+	/* Offset to be added to the translated address. */
+	unsigned int surfoffset;
+};
+
+/* Address fixup array. */
+#define GC_FIXUP_MAX 1024
+struct gcfixup {
+	/* Fixup list (gcfixup). */
+	struct list_head link;
+
+	/* Fixup array. */
+	unsigned int count;
+	struct gcfixupentry fixup[GC_FIXUP_MAX];
+};
+
+/* Defines a link list of scheduled unmappings. */
+struct gcschedunmap {
+	/* Map handle. */
+	unsigned long handle;
+
+	/* Previous/next unmapping info (gcschedunmap). */
+	struct list_head link;
+};
+
+
+/*******************************************************************************
+ * Map/unmap API entries.
+ */
+
+#define GCIOCTL_MAP   _IOWR(GCIOCTL_TYPE, GCIOCTL_BASE + 0x20, \
+			    struct gcimap)
+#define GCIOCTL_UNMAP _IOWR(GCIOCTL_TYPE, GCIOCTL_BASE + 0x21, \
+			    struct gcimap)
+
+struct gcimap {
+	/* Return status code. */
+	enum gcerror gcerror;
+
+	/* Mapped handle of the buffer. */
+	unsigned long handle;
+
+	union {
+		/* Pointer to the buffer to be mapped;
+		 * used when pagearray is not provided (set to NULL). */
+		void *logical;
+
+		/* Page offset of the buffer to be mapped;
+		 * used when pagearray is provided. */
+		unsigned int offset;
+	} buf;
+
+	/* Size of a physical page, 0 for  default. */
+	unsigned int pagesize;
+
+	/* Pointer to array of physical pages. */
+	unsigned long *pagearray;
+
+	/* Size of the buffer to be mappped. */
+	unsigned int size;
+};
+
+
+/*******************************************************************************
+ * Cache manipulation API entries.
+ */
+
+#define GCIOCTL_CACHE _IOW(GCIOCTL_TYPE, GCIOCTL_BASE + 0x30, \
+			   struct gcicache)
+
+struct gcicache {
+	/* Number of regions. */
+	int count;
+
+	/* The most regions that we deal with is 3. */
+	struct c2dmrgn rgn[3];
+
+	/* Direction of data. */
+	int dir;
+};
+
+
+/*******************************************************************************
+ * Callback API entry.
+ */
+
+#define GCIOCTL_CALLBACK_ALLOC _IOWR(GCIOCTL_TYPE, GCIOCTL_BASE + 0x40, \
+				     struct gcicallback)
+#define GCIOCTL_CALLBACK_FREE  _IOWR(GCIOCTL_TYPE, GCIOCTL_BASE + 0x41, \
+				     struct gcicallback)
+#define GCIOCTL_CALLBACK_WAIT  _IOWR(GCIOCTL_TYPE, GCIOCTL_BASE + 0x42, \
+				     struct gcicallbackwait)
+#define GCIOCTL_CALLBACK_ARM   _IOWR(GCIOCTL_TYPE, GCIOCTL_BASE + 0x43, \
+				     struct gcicallbackarm)
+
+/* GCIOCTL_CALLBACK_ALLOC / GCIOCTL_CALLBACK_FREE:
+ *   To be able to use the callback mechanism each user space client must
+ *   use the ALLOC/FREE APIs to manage a kernel side callback object
+ *   represented by the handle member of struct gcicallback.
+ *   ALLOC API allocates the object and returns the handle to it. */
+struct gcicallback {
+	/* Error code. */
+	enum gcerror gcerror;
+
+	/* Callback object handle. */
+	unsigned long handle;
+};
+
+/* GCIOCTL_CALLBACK_WAIT:
+ *   Called by the user level client to block and wait until the hardware
+ *   has executed a callback that was previosuly scheduled for the handle. */
+struct gcicallbackwait {
+	/* Error code. */
+	enum gcerror gcerror;
+
+	/* Callback object handle. */
+	unsigned long handle;
+
+	/* Timeout in milliseconds. */
+	unsigned long timeoutms;
+
+	/* OUT: if the call succeeds, callback and callbackparam are
+	 *      initialized with the callback to call. */
+	void (*callback) (void *callbackparam);
+	void *callbackparam;
+};
+
+/* GCIOCTL_CALLBACK_ARM:
+ *   Called by the client to arm a callback. This is similar to what
+ *   COMMIT API does, but in a separate API. */
+struct gcicallbackarm {
+	/* Return status code. */
+	enum gcerror gcerror;
+
+	/* Pointer to the callback function to be called when the GPU completes
+	 * execution of all buffers specified in this call. This member can be
+	 * NULL if no callback is desired. callbackparam specifies data to be
+	 * passed to the callback. */
+	void (*callback) (void *callbackparam);
+	void *callbackparam;
+
+	/* Callback object handle allocated with GCIOCTL_CALLBACK_ALLOC API. */
+	unsigned long handle;
+};
+
+#endif
diff --git a/include/linux/gcreg.h b/include/linux/gcreg.h
new file mode 100644
index 0000000..76ec725
--- /dev/null
+++ b/include/linux/gcreg.h
@@ -0,0 +1,10335 @@
+/*
+ * gcreg.h
+ *
+ * Copyright (C) 2010-2011 Vivante Corporation.
+ *
+ * This package is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#ifndef __gcreg_h
+#define __gcreg_h
+
+/*******************************************************************************
+** Register access macros.
+*/
+
+#define GCREGSTART(reg_field) \
+( \
+	0 ? reg_field \
+)
+
+#define GCREGEND(reg_field) \
+( \
+	1 ? reg_field \
+)
+
+#define GCREGSIZE(reg_field) \
+( \
+	GCREGEND(reg_field) - GCREGSTART(reg_field) + 1 \
+)
+
+#define GCREGALIGN(data, reg_field) \
+( \
+	((unsigned int) (data)) << GCREGSTART(reg_field) \
+)
+
+#define GCREGMASK(reg_field) \
+( \
+	GCREGALIGN(~0UL >> (32 - GCREGSIZE(reg_field)), reg_field) \
+)
+
+#define GCSETFIELDVAL(data, reg, field, value) \
+( \
+	(((unsigned int) (data)) & ~GCREGMASK(reg##_##field)) \
+	| (GCREGALIGN(reg##_##field##_##value, reg##_##field) \
+		& GCREGMASK(reg##_##field)) \
+)
+
+#define GCSETFIELD(data, reg, field, value) \
+( \
+	(((unsigned int) (data)) & ~GCREGMASK(reg##_##field)) \
+	| (GCREGALIGN((unsigned int) (value), reg##_##field) \
+		& GCREGMASK(reg##_##field)) \
+)
+
+#define GCGETFIELD(data, reg, field) \
+( \
+	(((unsigned int) (data)) & GCREGMASK(reg##_##field)) \
+	>> GCREGSTART(reg##_##field) \
+)
+
+#define GCREGVALUE(reg, field, val) \
+( \
+	reg##_##field##_##val \
+)
+
+/*******************************************************************************
+** Register gcregHiClockControl
+*/
+
+#define GCREG_HI_CLOCK_CONTROL_Address                                   0x00000
+#define GCREG_HI_CLOCK_CONTROL_MSB                                            15
+#define GCREG_HI_CLOCK_CONTROL_LSB                                             0
+#define GCREG_HI_CLOCK_CONTROL_BLK                                             0
+#define GCREG_HI_CLOCK_CONTROL_Count                                           1
+#define GCREG_HI_CLOCK_CONTROL_FieldMask                              0x000A17FE
+#define GCREG_HI_CLOCK_CONTROL_ReadMask                               0x000A17FE
+#define GCREG_HI_CLOCK_CONTROL_WriteMask                              0x000817FE
+#define GCREG_HI_CLOCK_CONTROL_ResetValue                             0x00000100
+
+/* Disable 3D clock. */
+#define GCREG_HI_CLOCK_CONTROL_CLK3D_DIS                                   0 : 0
+#define GCREG_HI_CLOCK_CONTROL_CLK3D_DIS_End                                   0
+#define GCREG_HI_CLOCK_CONTROL_CLK3D_DIS_Start                                 0
+#define GCREG_HI_CLOCK_CONTROL_CLK3D_DIS_Type                                U01
+
+/* Disable 2D clock. */
+#define GCREG_HI_CLOCK_CONTROL_CLK2D_DIS                                   1 : 1
+#define GCREG_HI_CLOCK_CONTROL_CLK2D_DIS_End                                   1
+#define GCREG_HI_CLOCK_CONTROL_CLK2D_DIS_Start                                 1
+#define GCREG_HI_CLOCK_CONTROL_CLK2D_DIS_Type                                U01
+
+#define GCREG_HI_CLOCK_CONTROL_FSCALE_VAL                                  8 : 2
+#define GCREG_HI_CLOCK_CONTROL_FSCALE_VAL_End                                  8
+#define GCREG_HI_CLOCK_CONTROL_FSCALE_VAL_Start                                2
+#define GCREG_HI_CLOCK_CONTROL_FSCALE_VAL_Type                               U07
+
+#define GCREG_HI_CLOCK_CONTROL_FSCALE_CMD_LOAD                             9 : 9
+#define GCREG_HI_CLOCK_CONTROL_FSCALE_CMD_LOAD_End                             9
+#define GCREG_HI_CLOCK_CONTROL_FSCALE_CMD_LOAD_Start                           9
+#define GCREG_HI_CLOCK_CONTROL_FSCALE_CMD_LOAD_Type                          U01
+
+/* Disables clock gating for rams. */
+#define GCREG_HI_CLOCK_CONTROL_DISABLE_RAM_CLK_GATING                    10 : 10
+#define GCREG_HI_CLOCK_CONTROL_DISABLE_RAM_CLK_GATING_End                     10
+#define GCREG_HI_CLOCK_CONTROL_DISABLE_RAM_CLK_GATING_Start                   10
+#define GCREG_HI_CLOCK_CONTROL_DISABLE_RAM_CLK_GATING_Type                   U01
+
+/* Disable debug registers. If this bit is 1, debug regs are clock gated. */
+#define GCREG_HI_CLOCK_CONTROL_DISABLE_DEBUG_REGISTERS                   11 : 11
+#define GCREG_HI_CLOCK_CONTROL_DISABLE_DEBUG_REGISTERS_End                    11
+#define GCREG_HI_CLOCK_CONTROL_DISABLE_DEBUG_REGISTERS_Start                  11
+#define GCREG_HI_CLOCK_CONTROL_DISABLE_DEBUG_REGISTERS_Type                  U01
+
+/* Soft resets the IP. */
+#define GCREG_HI_CLOCK_CONTROL_SOFT_RESET                                12 : 12
+#define GCREG_HI_CLOCK_CONTROL_SOFT_RESET_End                                 12
+#define GCREG_HI_CLOCK_CONTROL_SOFT_RESET_Start                               12
+#define GCREG_HI_CLOCK_CONTROL_SOFT_RESET_Type                               U01
+
+/* 3D pipe is idle. */
+#define GCREG_HI_CLOCK_CONTROL_IDLE_3D                                   16 : 16
+#define GCREG_HI_CLOCK_CONTROL_IDLE_3D_End                                    16
+#define GCREG_HI_CLOCK_CONTROL_IDLE_3D_Start                                  16
+#define GCREG_HI_CLOCK_CONTROL_IDLE_3D_Type                                  U01
+
+/* 2D pipe is idle. */
+#define GCREG_HI_CLOCK_CONTROL_IDLE_2D                                   17 : 17
+#define GCREG_HI_CLOCK_CONTROL_IDLE_2D_End                                    17
+#define GCREG_HI_CLOCK_CONTROL_IDLE_2D_Start                                  17
+#define GCREG_HI_CLOCK_CONTROL_IDLE_2D_Type                                  U01
+
+/* VG pipe is idle. */
+#define GCREG_HI_CLOCK_CONTROL_IDLE_VG                                   18 : 18
+#define GCREG_HI_CLOCK_CONTROL_IDLE_VG_End                                    18
+#define GCREG_HI_CLOCK_CONTROL_IDLE_VG_Start                                  18
+#define GCREG_HI_CLOCK_CONTROL_IDLE_VG_Type                                  U01
+
+/* Isolate GPU bit */
+#define GCREG_HI_CLOCK_CONTROL_ISOLATE_GPU                               19 : 19
+#define GCREG_HI_CLOCK_CONTROL_ISOLATE_GPU_End                                19
+#define GCREG_HI_CLOCK_CONTROL_ISOLATE_GPU_Start                              19
+#define GCREG_HI_CLOCK_CONTROL_ISOLATE_GPU_Type                              U01
+
+union gcclockcontrol {
+	struct {
+		/* gcregHiClockControl:
+			GCREG_HI_CLOCK_CONTROL_CLK3D_DIS */
+		unsigned int disable3d:1;
+
+		/* gcregHiClockControl:
+			GCREG_HI_CLOCK_CONTROL_CLK2D_DIS */
+		unsigned int disable2d:1;
+
+		/* gcregHiClockControl:
+			GCREG_HI_CLOCK_CONTROL_FSCALE_VAL */
+		unsigned int pulsecount:7;
+
+		/* gcregHiClockControl:
+			GCREG_HI_CLOCK_CONTROL_FSCALE_CMD_LOAD */
+		unsigned int pulseset:1;
+
+		/* gcregHiClockControl:
+			GCREG_HI_CLOCK_CONTROL_DISABLE_RAM_CLK_GATING */
+		unsigned int ramgate:1;
+
+		/* gcregHiClockControl:
+			GCREG_HI_CLOCK_CONTROL_DISABLE_DEBUG_REGISTERS */
+		unsigned int disabledbg:1;
+
+		/* gcregHiClockControl:
+			GCREG_HI_CLOCK_CONTROL_SOFT_RESET */
+		unsigned int reset:1;
+
+		/* gcregHiClockControl:
+			reserved */
+		unsigned int _reserved_13_15:3;
+
+		/* gcregHiClockControl:
+			GCREG_HI_CLOCK_CONTROL_IDLE_3D */
+		unsigned int idle3d:1;
+
+		/* gcregHiClockControl:
+			GCREG_HI_CLOCK_CONTROL_IDLE_2D */
+		unsigned int idle2d:1;
+
+		/* gcregHiClockControl:
+			GCREG_HI_CLOCK_CONTROL_IDLE_VG */
+		unsigned int idlevg:1;
+
+		/* gcregHiClockControl:
+			GCREG_HI_CLOCK_CONTROL_ISOLATE_GPU */
+		unsigned int isolate:1;
+
+		/* gcregHiClockControl:
+			reserved */
+		unsigned int _reserved_20_31:12;
+	} reg;
+
+	unsigned int raw;
+};
+
+/*******************************************************************************
+** Register gcregHiIdle
+*/
+
+#define GCREG_HI_IDLE_Address                                            0x00004
+#define GCREG_HI_IDLE_MSB                                                     15
+#define GCREG_HI_IDLE_LSB                                                      0
+#define GCREG_HI_IDLE_BLK                                                      0
+#define GCREG_HI_IDLE_Count                                                    1
+#define GCREG_HI_IDLE_FieldMask                                       0x80000007
+#define GCREG_HI_IDLE_ReadMask                                        0x80000007
+#define GCREG_HI_IDLE_WriteMask                                       0x00000000
+#define GCREG_HI_IDLE_ResetValue                                      0x00000007
+
+/* FE is idle. */
+#define GCREG_HI_IDLE_IDLE_FE                                              0 : 0
+#define GCREG_HI_IDLE_IDLE_FE_End                                              0
+#define GCREG_HI_IDLE_IDLE_FE_Start                                            0
+#define GCREG_HI_IDLE_IDLE_FE_Type                                           U01
+
+/* DE is idle. */
+#define GCREG_HI_IDLE_IDLE_DE                                              1 : 1
+#define GCREG_HI_IDLE_IDLE_DE_End                                              1
+#define GCREG_HI_IDLE_IDLE_DE_Start                                            1
+#define GCREG_HI_IDLE_IDLE_DE_Type                                           U01
+
+/* PE is idle. */
+#define GCREG_HI_IDLE_IDLE_PE                                              2 : 2
+#define GCREG_HI_IDLE_IDLE_PE_End                                              2
+#define GCREG_HI_IDLE_IDLE_PE_Start                                            2
+#define GCREG_HI_IDLE_IDLE_PE_Type                                           U01
+
+/* AXI is in low power mode. */
+#define GCREG_HI_IDLE_AXI_LP                                             31 : 31
+#define GCREG_HI_IDLE_AXI_LP_End                                              31
+#define GCREG_HI_IDLE_AXI_LP_Start                                            31
+#define GCREG_HI_IDLE_AXI_LP_Type                                            U01
+
+union gcidle {
+	struct {
+		/* gcregHiIdle: GCREG_HI_IDLE_IDLE_FE */
+		unsigned int fe:1;
+
+		/* gcregHiIdle: GCREG_HI_IDLE_IDLE_DE */
+		unsigned int de:1;
+
+		/* gcregHiIdle: GCREG_HI_IDLE_IDLE_PE */
+		unsigned int pe:1;
+
+		/* gcregHiIdle: reserved */
+		unsigned int _reserved_3_30:28;
+
+		/* gcregHiIdle: GCREG_HI_IDLE_AXI_LP */
+		unsigned int axilp:1;
+	} reg;
+
+	unsigned int raw;
+};
+
+/*******************************************************************************
+** Register gcregAxiConfig
+*/
+
+#define GCREG_AXI_CONFIG_Address                                         0x00008
+#define GCREG_AXI_CONFIG_MSB                                                  15
+#define GCREG_AXI_CONFIG_LSB                                                   0
+#define GCREG_AXI_CONFIG_BLK                                                   0
+#define GCREG_AXI_CONFIG_Count                                                 1
+#define GCREG_AXI_CONFIG_FieldMask                                    0x0000FFFF
+#define GCREG_AXI_CONFIG_ReadMask                                     0x0000FFFF
+#define GCREG_AXI_CONFIG_WriteMask                                    0x0000FFFF
+#define GCREG_AXI_CONFIG_ResetValue                                   0x00000000
+
+#define GCREG_AXI_CONFIG_AWID                                              3 : 0
+#define GCREG_AXI_CONFIG_AWID_End                                              3
+#define GCREG_AXI_CONFIG_AWID_Start                                            0
+#define GCREG_AXI_CONFIG_AWID_Type                                           U04
+
+#define GCREG_AXI_CONFIG_ARID                                              7 : 4
+#define GCREG_AXI_CONFIG_ARID_End                                              7
+#define GCREG_AXI_CONFIG_ARID_Start                                            4
+#define GCREG_AXI_CONFIG_ARID_Type                                           U04
+
+#define GCREG_AXI_CONFIG_AWCACHE                                          11 : 8
+#define GCREG_AXI_CONFIG_AWCACHE_End                                          11
+#define GCREG_AXI_CONFIG_AWCACHE_Start                                         8
+#define GCREG_AXI_CONFIG_AWCACHE_Type                                        U04
+
+#define GCREG_AXI_CONFIG_ARCACHE                                         15 : 12
+#define GCREG_AXI_CONFIG_ARCACHE_End                                          15
+#define GCREG_AXI_CONFIG_ARCACHE_Start                                        12
+#define GCREG_AXI_CONFIG_ARCACHE_Type                                        U04
+
+/*******************************************************************************
+** Register gcregAxiStatus
+*/
+
+#define GCREG_AXI_STATUS_Address                                         0x0000C
+#define GCREG_AXI_STATUS_MSB                                                  15
+#define GCREG_AXI_STATUS_LSB                                                   0
+#define GCREG_AXI_STATUS_BLK                                                   0
+#define GCREG_AXI_STATUS_Count                                                 1
+#define GCREG_AXI_STATUS_FieldMask                                    0x000003FF
+#define GCREG_AXI_STATUS_ReadMask                                     0x000003FF
+#define GCREG_AXI_STATUS_WriteMask                                    0x00000000
+#define GCREG_AXI_STATUS_ResetValue                                   0x00000000
+
+#define GCREG_AXI_STATUS_DET_RD_ERR                                        9 : 9
+#define GCREG_AXI_STATUS_DET_RD_ERR_End                                        9
+#define GCREG_AXI_STATUS_DET_RD_ERR_Start                                      9
+#define GCREG_AXI_STATUS_DET_RD_ERR_Type                                     U01
+
+#define GCREG_AXI_STATUS_DET_WR_ERR                                        8 : 8
+#define GCREG_AXI_STATUS_DET_WR_ERR_End                                        8
+#define GCREG_AXI_STATUS_DET_WR_ERR_Start                                      8
+#define GCREG_AXI_STATUS_DET_WR_ERR_Type                                     U01
+
+#define GCREG_AXI_STATUS_RD_ERR_ID                                         7 : 4
+#define GCREG_AXI_STATUS_RD_ERR_ID_End                                         7
+#define GCREG_AXI_STATUS_RD_ERR_ID_Start                                       4
+#define GCREG_AXI_STATUS_RD_ERR_ID_Type                                      U04
+
+#define GCREG_AXI_STATUS_WR_ERR_ID                                         3 : 0
+#define GCREG_AXI_STATUS_WR_ERR_ID_End                                         3
+#define GCREG_AXI_STATUS_WR_ERR_ID_Start                                       0
+#define GCREG_AXI_STATUS_WR_ERR_ID_Type                                      U04
+
+/*******************************************************************************
+** Register gcregIntrAcknowledge
+*/
+
+/* Interrupt acknowledge register. Each bit represents a corresponding event
+** being triggered. Reading from this register clears the outstanding interrupt.
+*/
+
+#define GCREG_INTR_ACKNOWLEDGE_Address                                   0x00010
+#define GCREG_INTR_ACKNOWLEDGE_MSB                                            15
+#define GCREG_INTR_ACKNOWLEDGE_LSB                                             0
+#define GCREG_INTR_ACKNOWLEDGE_BLK                                             0
+#define GCREG_INTR_ACKNOWLEDGE_Count                                           1
+#define GCREG_INTR_ACKNOWLEDGE_FieldMask                              0xFFFFFFFF
+#define GCREG_INTR_ACKNOWLEDGE_ReadMask                               0xFFFFFFFF
+#define GCREG_INTR_ACKNOWLEDGE_WriteMask                              0x00000000
+#define GCREG_INTR_ACKNOWLEDGE_ResetValue                             0x00000000
+
+#define GCREG_INTR_ACKNOWLEDGE_INTR_VEC                                   31 : 0
+#define GCREG_INTR_ACKNOWLEDGE_INTR_VEC_End                                   31
+#define GCREG_INTR_ACKNOWLEDGE_INTR_VEC_Start                                  0
+#define GCREG_INTR_ACKNOWLEDGE_INTR_VEC_Type                                 U32
+
+/*******************************************************************************
+** Register gcregIntrEnbl
+*/
+
+/* Interrupt enable register. Each bit enables a corresponding event. */
+
+#define GCREG_INTR_ENBL_Address                                          0x00014
+#define GCREG_INTR_ENBL_MSB                                                   15
+#define GCREG_INTR_ENBL_LSB                                                    0
+#define GCREG_INTR_ENBL_BLK                                                    0
+#define GCREG_INTR_ENBL_Count                                                  1
+#define GCREG_INTR_ENBL_FieldMask                                     0xFFFFFFFF
+#define GCREG_INTR_ENBL_ReadMask                                      0xFFFFFFFF
+#define GCREG_INTR_ENBL_WriteMask                                     0xFFFFFFFF
+#define GCREG_INTR_ENBL_ResetValue                                    0x00000000
+
+#define GCREG_INTR_ENBL_INTR_ENBL_VEC                                     31 : 0
+#define GCREG_INTR_ENBL_INTR_ENBL_VEC_End                                     31
+#define GCREG_INTR_ENBL_INTR_ENBL_VEC_Start                                    0
+#define GCREG_INTR_ENBL_INTR_ENBL_VEC_Type                                   U32
+
+/*******************************************************************************
+** Register GCFeatures
+*/
+
+/* Shows which features are enabled in this chip.  This register has no set
+** reset value.  It varies with the implementation.
+*/
+
+#define GC_FEATURES_Address                                              0x0001C
+#define GC_FEATURES_MSB                                                       15
+#define GC_FEATURES_LSB                                                        0
+#define GC_FEATURES_BLK                                                        0
+#define GC_FEATURES_Count                                                      1
+#define GC_FEATURES_FieldMask                                         0xFFFFFFFF
+#define GC_FEATURES_ReadMask                                          0xFFFFFFFF
+#define GC_FEATURES_WriteMask                                         0x00000000
+#define GC_FEATURES_ResetValue                                        0x00000000
+
+/* Fast clear. */
+#define GC_FEATURES_FAST_CLEAR                                             0 : 0
+#define GC_FEATURES_FAST_CLEAR_End                                             0
+#define GC_FEATURES_FAST_CLEAR_Start                                           0
+#define GC_FEATURES_FAST_CLEAR_Type                                          U01
+#define   GC_FEATURES_FAST_CLEAR_NONE                                        0x0
+#define   GC_FEATURES_FAST_CLEAR_AVAILABLE                                   0x1
+
+/* Full-screen anti-aliasing. */
+#define GC_FEATURES_SPECIAL_ANTI_ALIASING                                  1 : 1
+#define GC_FEATURES_SPECIAL_ANTI_ALIASING_End                                  1
+#define GC_FEATURES_SPECIAL_ANTI_ALIASING_Start                                1
+#define GC_FEATURES_SPECIAL_ANTI_ALIASING_Type                               U01
+#define   GC_FEATURES_SPECIAL_ANTI_ALIASING_NONE                             0x0
+#define   GC_FEATURES_SPECIAL_ANTI_ALIASING_AVAILABLE                        0x1
+
+/* 3D pipe. */
+#define GC_FEATURES_PIPE_3D                                                2 : 2
+#define GC_FEATURES_PIPE_3D_End                                                2
+#define GC_FEATURES_PIPE_3D_Start                                              2
+#define GC_FEATURES_PIPE_3D_Type                                             U01
+#define   GC_FEATURES_PIPE_3D_NONE                                           0x0
+#define   GC_FEATURES_PIPE_3D_AVAILABLE                                      0x1
+
+/* DXT texture compression. */
+#define GC_FEATURES_DXT_TEXTURE_COMPRESSION                                3 : 3
+#define GC_FEATURES_DXT_TEXTURE_COMPRESSION_End                                3
+#define GC_FEATURES_DXT_TEXTURE_COMPRESSION_Start                              3
+#define GC_FEATURES_DXT_TEXTURE_COMPRESSION_Type                             U01
+#define   GC_FEATURES_DXT_TEXTURE_COMPRESSION_NONE                           0x0
+#define   GC_FEATURES_DXT_TEXTURE_COMPRESSION_AVAILABLE                      0x1
+
+/* Debug registers. */
+#define GC_FEATURES_DEBUG_MODE                                             4 : 4
+#define GC_FEATURES_DEBUG_MODE_End                                             4
+#define GC_FEATURES_DEBUG_MODE_Start                                           4
+#define GC_FEATURES_DEBUG_MODE_Type                                          U01
+#define   GC_FEATURES_DEBUG_MODE_NONE                                        0x0
+#define   GC_FEATURES_DEBUG_MODE_AVAILABLE                                   0x1
+
+/* Depth and color compression. */
+#define GC_FEATURES_ZCOMPRESSION                                           5 : 5
+#define GC_FEATURES_ZCOMPRESSION_End                                           5
+#define GC_FEATURES_ZCOMPRESSION_Start                                         5
+#define GC_FEATURES_ZCOMPRESSION_Type                                        U01
+#define   GC_FEATURES_ZCOMPRESSION_NONE                                      0x0
+#define   GC_FEATURES_ZCOMPRESSION_AVAILABLE                                 0x1
+
+/* YUV 4:2:0 support in filter blit. */
+#define GC_FEATURES_YUV420_FILTER                                          6 : 6
+#define GC_FEATURES_YUV420_FILTER_End                                          6
+#define GC_FEATURES_YUV420_FILTER_Start                                        6
+#define GC_FEATURES_YUV420_FILTER_Type                                       U01
+#define   GC_FEATURES_YUV420_FILTER_NONE                                     0x0
+#define   GC_FEATURES_YUV420_FILTER_AVAILABLE                                0x1
+
+/* MSAA support. */
+#define GC_FEATURES_MSAA                                                   7 : 7
+#define GC_FEATURES_MSAA_End                                                   7
+#define GC_FEATURES_MSAA_Start                                                 7
+#define GC_FEATURES_MSAA_Type                                                U01
+#define   GC_FEATURES_MSAA_NONE                                              0x0
+#define   GC_FEATURES_MSAA_AVAILABLE                                         0x1
+
+/* Shows if there is a display controller in the IP. */
+#define GC_FEATURES_DC                                                     8 : 8
+#define GC_FEATURES_DC_End                                                     8
+#define GC_FEATURES_DC_Start                                                   8
+#define GC_FEATURES_DC_Type                                                  U01
+#define   GC_FEATURES_DC_NONE                                                0x0
+#define   GC_FEATURES_DC_AVAILABLE                                           0x1
+
+/* Shows if there is 2D engine. */
+#define GC_FEATURES_PIPE_2D                                                9 : 9
+#define GC_FEATURES_PIPE_2D_End                                                9
+#define GC_FEATURES_PIPE_2D_Start                                              9
+#define GC_FEATURES_PIPE_2D_Type                                             U01
+#define   GC_FEATURES_PIPE_2D_NONE                                           0x0
+#define   GC_FEATURES_PIPE_2D_AVAILABLE                                      0x1
+
+/* ETC1 texture compression. */
+#define GC_FEATURES_ETC1_TEXTURE_COMPRESSION                             10 : 10
+#define GC_FEATURES_ETC1_TEXTURE_COMPRESSION_End                              10
+#define GC_FEATURES_ETC1_TEXTURE_COMPRESSION_Start                            10
+#define GC_FEATURES_ETC1_TEXTURE_COMPRESSION_Type                            U01
+#define   GC_FEATURES_ETC1_TEXTURE_COMPRESSION_NONE                          0x0
+#define   GC_FEATURES_ETC1_TEXTURE_COMPRESSION_AVAILABLE                     0x1
+
+/* Shows if the IP has HD scaler. */
+#define GC_FEATURES_FAST_SCALER                                          11 : 11
+#define GC_FEATURES_FAST_SCALER_End                                           11
+#define GC_FEATURES_FAST_SCALER_Start                                         11
+#define GC_FEATURES_FAST_SCALER_Type                                         U01
+#define   GC_FEATURES_FAST_SCALER_NONE                                       0x0
+#define   GC_FEATURES_FAST_SCALER_AVAILABLE                                  0x1
+
+/* Shows if the IP has HDR support. */
+#define GC_FEATURES_HIGH_DYNAMIC_RANGE                                   12 : 12
+#define GC_FEATURES_HIGH_DYNAMIC_RANGE_End                                    12
+#define GC_FEATURES_HIGH_DYNAMIC_RANGE_Start                                  12
+#define GC_FEATURES_HIGH_DYNAMIC_RANGE_Type                                  U01
+#define   GC_FEATURES_HIGH_DYNAMIC_RANGE_NONE                                0x0
+#define   GC_FEATURES_HIGH_DYNAMIC_RANGE_AVAILABLE                           0x1
+
+/* YUV 4:2:0 tiler is available. */
+#define GC_FEATURES_YUV420_TILER                                         13 : 13
+#define GC_FEATURES_YUV420_TILER_End                                          13
+#define GC_FEATURES_YUV420_TILER_Start                                        13
+#define GC_FEATURES_YUV420_TILER_Type                                        U01
+#define   GC_FEATURES_YUV420_TILER_NONE                                      0x0
+#define   GC_FEATURES_YUV420_TILER_AVAILABLE                                 0x1
+
+/* Second level clock gating is available. */
+#define GC_FEATURES_MODULE_CG                                            14 : 14
+#define GC_FEATURES_MODULE_CG_End                                             14
+#define GC_FEATURES_MODULE_CG_Start                                           14
+#define GC_FEATURES_MODULE_CG_Type                                           U01
+#define   GC_FEATURES_MODULE_CG_NONE                                         0x0
+#define   GC_FEATURES_MODULE_CG_AVAILABLE                                    0x1
+
+/* IP is configured to have minimum area. */
+#define GC_FEATURES_MIN_AREA                                             15 : 15
+#define GC_FEATURES_MIN_AREA_End                                              15
+#define GC_FEATURES_MIN_AREA_Start                                            15
+#define GC_FEATURES_MIN_AREA_Type                                            U01
+#define   GC_FEATURES_MIN_AREA_NONE                                          0x0
+#define   GC_FEATURES_MIN_AREA_AVAILABLE                                     0x1
+
+/* IP does not have early-Z. */
+#define GC_FEATURES_NO_EZ                                                16 : 16
+#define GC_FEATURES_NO_EZ_End                                                 16
+#define GC_FEATURES_NO_EZ_Start                                               16
+#define GC_FEATURES_NO_EZ_Type                                               U01
+#define   GC_FEATURES_NO_EZ_NONE                                             0x0
+#define   GC_FEATURES_NO_EZ_AVAILABLE                                        0x1
+
+/* IP does not have 422 texture input format. */
+#define GC_FEATURES_NO422_TEXTURE                                        17 : 17
+#define GC_FEATURES_NO422_TEXTURE_End                                         17
+#define GC_FEATURES_NO422_TEXTURE_Start                                       17
+#define GC_FEATURES_NO422_TEXTURE_Type                                       U01
+#define   GC_FEATURES_NO422_TEXTURE_NONE                                     0x0
+#define   GC_FEATURES_NO422_TEXTURE_AVAILABLE                                0x1
+
+/* IP supports interleaving depth and color buffers. */
+#define GC_FEATURES_BUFFER_INTERLEAVING                                  18 : 18
+#define GC_FEATURES_BUFFER_INTERLEAVING_End                                   18
+#define GC_FEATURES_BUFFER_INTERLEAVING_Start                                 18
+#define GC_FEATURES_BUFFER_INTERLEAVING_Type                                 U01
+#define   GC_FEATURES_BUFFER_INTERLEAVING_NONE                               0x0
+#define   GC_FEATURES_BUFFER_INTERLEAVING_AVAILABLE                          0x1
+
+/* Supports byte write in 2D. */
+#define GC_FEATURES_BYTE_WRITE_2D                                        19 : 19
+#define GC_FEATURES_BYTE_WRITE_2D_End                                         19
+#define GC_FEATURES_BYTE_WRITE_2D_Start                                       19
+#define GC_FEATURES_BYTE_WRITE_2D_Type                                       U01
+#define   GC_FEATURES_BYTE_WRITE_2D_NONE                                     0x0
+#define   GC_FEATURES_BYTE_WRITE_2D_AVAILABLE                                0x1
+
+/* IP does not have 2D scaler. */
+#define GC_FEATURES_NO_SCALER                                            20 : 20
+#define GC_FEATURES_NO_SCALER_End                                             20
+#define GC_FEATURES_NO_SCALER_Start                                           20
+#define GC_FEATURES_NO_SCALER_Type                                           U01
+#define   GC_FEATURES_NO_SCALER_NONE                                         0x0
+#define   GC_FEATURES_NO_SCALER_AVAILABLE                                    0x1
+
+/* YUY2 averaging support in resolve. */
+#define GC_FEATURES_YUY2_AVERAGING                                       21 : 21
+#define GC_FEATURES_YUY2_AVERAGING_End                                        21
+#define GC_FEATURES_YUY2_AVERAGING_Start                                      21
+#define GC_FEATURES_YUY2_AVERAGING_Type                                      U01
+#define   GC_FEATURES_YUY2_AVERAGING_NONE                                    0x0
+#define   GC_FEATURES_YUY2_AVERAGING_AVAILABLE                               0x1
+
+/* PE cache is half. */
+#define GC_FEATURES_HALF_PE_CACHE                                        22 : 22
+#define GC_FEATURES_HALF_PE_CACHE_End                                         22
+#define GC_FEATURES_HALF_PE_CACHE_Start                                       22
+#define GC_FEATURES_HALF_PE_CACHE_Type                                       U01
+#define   GC_FEATURES_HALF_PE_CACHE_NONE                                     0x0
+#define   GC_FEATURES_HALF_PE_CACHE_AVAILABLE                                0x1
+
+/* TX cache is half. */
+#define GC_FEATURES_HALF_TX_CACHE                                        23 : 23
+#define GC_FEATURES_HALF_TX_CACHE_End                                         23
+#define GC_FEATURES_HALF_TX_CACHE_Start                                       23
+#define GC_FEATURES_HALF_TX_CACHE_Type                                       U01
+#define   GC_FEATURES_HALF_TX_CACHE_NONE                                     0x0
+#define   GC_FEATURES_HALF_TX_CACHE_AVAILABLE                                0x1
+
+/* YUY2 support in PE and YUY2 to RGB conversion in resolve. */
+#define GC_FEATURES_YUY2_RENDER_TARGET                                   24 : 24
+#define GC_FEATURES_YUY2_RENDER_TARGET_End                                    24
+#define GC_FEATURES_YUY2_RENDER_TARGET_Start                                  24
+#define GC_FEATURES_YUY2_RENDER_TARGET_Type                                  U01
+#define   GC_FEATURES_YUY2_RENDER_TARGET_NONE                                0x0
+#define   GC_FEATURES_YUY2_RENDER_TARGET_AVAILABLE                           0x1
+
+/* 32 bit memory address support. */
+#define GC_FEATURES_MEM32_BIT_SUPPORT                                    25 : 25
+#define GC_FEATURES_MEM32_BIT_SUPPORT_End                                     25
+#define GC_FEATURES_MEM32_BIT_SUPPORT_Start                                   25
+#define GC_FEATURES_MEM32_BIT_SUPPORT_Type                                   U01
+#define   GC_FEATURES_MEM32_BIT_SUPPORT_NONE                                 0x0
+#define   GC_FEATURES_MEM32_BIT_SUPPORT_AVAILABLE                            0x1
+
+/* VG pipe is present. */
+#define GC_FEATURES_PIPE_VG                                              26 : 26
+#define GC_FEATURES_PIPE_VG_End                                               26
+#define GC_FEATURES_PIPE_VG_Start                                             26
+#define GC_FEATURES_PIPE_VG_Type                                             U01
+#define   GC_FEATURES_PIPE_VG_NONE                                           0x0
+#define   GC_FEATURES_PIPE_VG_AVAILABLE                                      0x1
+
+/* VG tesselator is present. */
+#define GC_FEATURES_VGTS                                                 27 : 27
+#define GC_FEATURES_VGTS_End                                                  27
+#define GC_FEATURES_VGTS_Start                                                27
+#define GC_FEATURES_VGTS_Type                                                U01
+#define   GC_FEATURES_VGTS_NONE                                              0x0
+#define   GC_FEATURES_VGTS_AVAILABLE                                         0x1
+
+/* FE 2.0 is present. */
+#define GC_FEATURES_FE20                                                 28 : 28
+#define GC_FEATURES_FE20_End                                                  28
+#define GC_FEATURES_FE20_Start                                                28
+#define GC_FEATURES_FE20_Type                                                U01
+#define   GC_FEATURES_FE20_NONE                                              0x0
+#define   GC_FEATURES_FE20_AVAILABLE                                         0x1
+
+/* 3D PE has byte write capability. */
+#define GC_FEATURES_BYTE_WRITE_3D                                        29 : 29
+#define GC_FEATURES_BYTE_WRITE_3D_End                                         29
+#define GC_FEATURES_BYTE_WRITE_3D_Start                                       29
+#define GC_FEATURES_BYTE_WRITE_3D_Type                                       U01
+#define   GC_FEATURES_BYTE_WRITE_3D_NONE                                     0x0
+#define   GC_FEATURES_BYTE_WRITE_3D_AVAILABLE                                0x1
+
+/* Supports resolveing into YUV target. */
+#define GC_FEATURES_RS_YUV_TARGET                                        30 : 30
+#define GC_FEATURES_RS_YUV_TARGET_End                                         30
+#define GC_FEATURES_RS_YUV_TARGET_Start                                       30
+#define GC_FEATURES_RS_YUV_TARGET_Type                                       U01
+#define   GC_FEATURES_RS_YUV_TARGET_NONE                                     0x0
+#define   GC_FEATURES_RS_YUV_TARGET_AVAILABLE                                0x1
+
+/* Supports 20 bit index. */
+#define GC_FEATURES_FE20_BIT_INDEX                                       31 : 31
+#define GC_FEATURES_FE20_BIT_INDEX_End                                        31
+#define GC_FEATURES_FE20_BIT_INDEX_Start                                      31
+#define GC_FEATURES_FE20_BIT_INDEX_Type                                      U01
+#define   GC_FEATURES_FE20_BIT_INDEX_NONE                                    0x0
+#define   GC_FEATURES_FE20_BIT_INDEX_AVAILABLE                               0x1
+
+union gcfeatures {
+	struct {
+		/* GC_FEATURES_Address:FAST_CLEAR */
+		unsigned int fastclear:1;
+
+		/* GC_FEATURES_Address:SPECIAL_ANTI_ALIASING */
+		unsigned int specialantialiasing:1;
+
+		/* GC_FEATURES_Address:PIPE_3D */
+		unsigned int pipe3d:1;
+
+		/* GC_FEATURES_Address:DXT_TEXTURE_COMPRESSION */
+		unsigned int dxt:1;
+
+		/* GC_FEATURES_Address:DEBUG_MODE */
+		unsigned int debugmode:1;
+
+		/* GC_FEATURES_Address:ZCOMPRESSION */
+		unsigned int zcompression:1;
+
+		/* GC_FEATURES_Address:YUV420_FILTER */
+		unsigned int yuv420filter:1;
+
+		/* GC_FEATURES_Address:MSAA */
+		unsigned int msaa:1;
+
+		/* GC_FEATURES_Address:DC */
+		unsigned int dc:1;
+
+		/* GC_FEATURES_Address:PIPE_2D */
+		unsigned int pipe2d:1;
+
+		/* GC_FEATURES_Address:ETC1_TEXTURE_COMPRESSION */
+		unsigned int etc:1;
+
+		/* GC_FEATURES_Address:FAST_SCALER */
+		unsigned int fastscaler:1;
+
+		/* GC_FEATURES_Address:HIGH_DYNAMIC_RANGE */
+		unsigned int hdr:1;
+
+		/* GC_FEATURES_Address:YUV420_TILER */
+		unsigned int yuv420tiler:1;
+
+		/* GC_FEATURES_Address:MODULE_CG */
+		unsigned int clockgating:1;
+
+		/* GC_FEATURES_Address:MIN_AREA */
+		unsigned int minarea:1;
+
+		/* GC_FEATURES_Address:NO_EZ */
+		unsigned int noez:1;
+
+		/* GC_FEATURES_Address:NO422_TEXTURE */
+		unsigned int no422texture:1;
+
+		/* GC_FEATURES_Address:BUFFER_INTERLEAVING */
+		unsigned int bufinterleaving:1;
+
+		/* GC_FEATURES_Address:BYTE_WRITE_2D */
+		unsigned int bytewrite2d:1;
+
+		/* GC_FEATURES_Address:NO_SCALER */
+		unsigned int noscaler:1;
+
+		/* GC_FEATURES_Address:YUY2_AVERAGING */
+		unsigned int yuy2averaging:1;
+
+		/* GC_FEATURES_Address:HALF_PE_CACHE */
+		unsigned int halfpecache:1;
+
+		/* GC_FEATURES_Address:HALF_TX_CACHE */
+		unsigned int halftxcache:1;
+
+		/* GC_FEATURES_Address:YUY2_RENDER_TARGET */
+		unsigned int yuy2target:1;
+
+		/* GC_FEATURES_Address:MEM32_BIT_SUPPORT */
+		unsigned int mem32:1;
+
+		/* GC_FEATURES_Address:PIPE_VG */
+		unsigned int pipevg:1;
+
+		/* GC_FEATURES_Address:VGTS */
+		unsigned int vgts:1;
+
+		/* GC_FEATURES_Address:FE20 */
+		unsigned int fe20:1;
+
+		/* GC_FEATURES_Address:BYTE_WRITE_3D */
+		unsigned int bytewrite3d:1;
+
+		/* GC_FEATURES_Address:RS_YUV_TARGET */
+		unsigned int rsyuvtarget:1;
+
+		/* GC_FEATURES_Address:FE20_BIT_INDEX */
+		unsigned int fe20bit:1;
+	} reg;
+
+	unsigned int raw;
+};
+
+/*******************************************************************************
+** Register GCChipId
+*/
+
+/* Shows the ID for the chip in BCD.  This register has no set reset value.
+** It varies with the implementation.
+*/
+
+#define GC_CHIP_ID_Address                                               0x00020
+#define GC_CHIP_ID_MSB                                                        15
+#define GC_CHIP_ID_LSB                                                         0
+#define GC_CHIP_ID_BLK                                                         0
+#define GC_CHIP_ID_Count                                                       1
+#define GC_CHIP_ID_FieldMask                                          0xFFFFFFFF
+#define GC_CHIP_ID_ReadMask                                           0xFFFFFFFF
+#define GC_CHIP_ID_WriteMask                                          0x00000000
+#define GC_CHIP_ID_ResetValue                                         0x00000000
+
+/* Id. */
+#define GC_CHIP_ID_ID                                                     31 : 0
+#define GC_CHIP_ID_ID_End                                                     31
+#define GC_CHIP_ID_ID_Start                                                    0
+#define GC_CHIP_ID_ID_Type                                                   U32
+
+/*******************************************************************************
+** Register GCChipRev
+*/
+
+/* Shows the revision for the chip in BCD.  This register has no set reset
+** value.  It varies with the implementation.
+*/
+
+#define GC_CHIP_REV_Address                                              0x00024
+#define GC_CHIP_REV_MSB                                                       15
+#define GC_CHIP_REV_LSB                                                        0
+#define GC_CHIP_REV_BLK                                                        0
+#define GC_CHIP_REV_Count                                                      1
+#define GC_CHIP_REV_FieldMask                                         0xFFFFFFFF
+#define GC_CHIP_REV_ReadMask                                          0xFFFFFFFF
+#define GC_CHIP_REV_WriteMask                                         0x00000000
+#define GC_CHIP_REV_ResetValue                                        0x00000000
+
+/* Revision. */
+#define GC_CHIP_REV_REV                                                   31 : 0
+#define GC_CHIP_REV_REV_End                                                   31
+#define GC_CHIP_REV_REV_Start                                                  0
+#define GC_CHIP_REV_REV_Type                                                 U32
+
+/*******************************************************************************
+** Register GCChipDate
+*/
+
+/* Shows the release date for the IP.  This register has no set reset value.
+** It varies with the implementation.
+*/
+
+#define GC_CHIP_DATE_Address                                             0x00028
+#define GC_CHIP_DATE_MSB                                                      15
+#define GC_CHIP_DATE_LSB                                                       0
+#define GC_CHIP_DATE_BLK                                                       0
+#define GC_CHIP_DATE_Count                                                     1
+#define GC_CHIP_DATE_FieldMask                                        0xFFFFFFFF
+#define GC_CHIP_DATE_ReadMask                                         0xFFFFFFFF
+#define GC_CHIP_DATE_WriteMask                                        0x00000000
+#define GC_CHIP_DATE_ResetValue                                       0x00000000
+
+/* Date. */
+#define GC_CHIP_DATE_DATE                                                 31 : 0
+#define GC_CHIP_DATE_DATE_End                                                 31
+#define GC_CHIP_DATE_DATE_Start                                                0
+#define GC_CHIP_DATE_DATE_Type                                               U32
+
+/*******************************************************************************
+** Register GCChipTime
+*/
+
+/* Shows the release time for the IP.  This register has no set reset value.
+** It varies with the implementation.
+*/
+
+#define GC_CHIP_TIME_Address                                             0x0002C
+#define GC_CHIP_TIME_MSB                                                      15
+#define GC_CHIP_TIME_LSB                                                       0
+#define GC_CHIP_TIME_BLK                                                       0
+#define GC_CHIP_TIME_Count                                                     1
+#define GC_CHIP_TIME_FieldMask                                        0xFFFFFFFF
+#define GC_CHIP_TIME_ReadMask                                         0xFFFFFFFF
+#define GC_CHIP_TIME_WriteMask                                        0x00000000
+#define GC_CHIP_TIME_ResetValue                                       0x00000000
+
+/* Time. */
+#define GC_CHIP_TIME_TIME                                                 31 : 0
+#define GC_CHIP_TIME_TIME_End                                                 31
+#define GC_CHIP_TIME_TIME_Start                                                0
+#define GC_CHIP_TIME_TIME_Type                                               U32
+
+/*******************************************************************************
+** Register GCMinorFeatures0
+*/
+
+/* Shows which minor features are enabled in this chip.  This register has no
+** set reset value.  It varies with the implementation.
+*/
+
+#define GC_FEATURES0_Address                                             0x00034
+#define GC_FEATURES0_MSB                                                      15
+#define GC_FEATURES0_LSB                                                       0
+#define GC_FEATURES0_BLK                                                       0
+#define GC_FEATURES0_Count                                                     1
+#define GC_FEATURES0_FieldMask                                        0xFFFFFFFF
+#define GC_FEATURES0_ReadMask                                         0xFFFFFFFF
+#define GC_FEATURES0_WriteMask                                        0x00000000
+#define GC_FEATURES0_ResetValue                                       0x00000000
+
+/* Y flipping capability is added to resolve. */
+#define GC_FEATURES0_FLIP_Y                                                0 : 0
+#define GC_FEATURES0_FLIP_Y_End                                                0
+#define GC_FEATURES0_FLIP_Y_Start                                              0
+#define GC_FEATURES0_FLIP_Y_Type                                             U01
+#define   GC_FEATURES0_FLIP_Y_NONE                                           0x0
+#define   GC_FEATURES0_FLIP_Y_AVAILABLE                                      0x1
+
+/* Dual Return Bus from HI to clients. */
+#define GC_FEATURES0_DUAL_RETURN_BUS                                       1 : 1
+#define GC_FEATURES0_DUAL_RETURN_BUS_End                                       1
+#define GC_FEATURES0_DUAL_RETURN_BUS_Start                                     1
+#define GC_FEATURES0_DUAL_RETURN_BUS_Type                                    U01
+#define   GC_FEATURES0_DUAL_RETURN_BUS_NONE                                  0x0
+#define   GC_FEATURES0_DUAL_RETURN_BUS_AVAILABLE                             0x1
+
+/* Configurable endianness support. */
+#define GC_FEATURES0_ENDIANNESS_CONFIG                                     2 : 2
+#define GC_FEATURES0_ENDIANNESS_CONFIG_End                                     2
+#define GC_FEATURES0_ENDIANNESS_CONFIG_Start                                   2
+#define GC_FEATURES0_ENDIANNESS_CONFIG_Type                                  U01
+#define   GC_FEATURES0_ENDIANNESS_CONFIG_NONE                                0x0
+#define   GC_FEATURES0_ENDIANNESS_CONFIG_AVAILABLE                           0x1
+
+/* Supports 8Kx8K textures. */
+#define GC_FEATURES0_TEXTURE8_K                                            3 : 3
+#define GC_FEATURES0_TEXTURE8_K_End                                            3
+#define GC_FEATURES0_TEXTURE8_K_Start                                          3
+#define GC_FEATURES0_TEXTURE8_K_Type                                         U01
+#define   GC_FEATURES0_TEXTURE8_K_NONE                                       0x0
+#define   GC_FEATURES0_TEXTURE8_K_AVAILABLE                                  0x1
+
+/* Driver hack is not needed. */
+#define GC_FEATURES0_CORRECT_TEXTURE_CONVERTER                             4 : 4
+#define GC_FEATURES0_CORRECT_TEXTURE_CONVERTER_End                             4
+#define GC_FEATURES0_CORRECT_TEXTURE_CONVERTER_Start                           4
+#define GC_FEATURES0_CORRECT_TEXTURE_CONVERTER_Type                          U01
+#define   GC_FEATURES0_CORRECT_TEXTURE_CONVERTER_NONE                        0x0
+#define   GC_FEATURES0_CORRECT_TEXTURE_CONVERTER_AVAILABLE                   0x1
+
+/* Special LOD calculation when MSAA is on. */
+#define GC_FEATURES0_SPECIAL_MSAA_LOD                                      5 : 5
+#define GC_FEATURES0_SPECIAL_MSAA_LOD_End                                      5
+#define GC_FEATURES0_SPECIAL_MSAA_LOD_Start                                    5
+#define GC_FEATURES0_SPECIAL_MSAA_LOD_Type                                   U01
+#define   GC_FEATURES0_SPECIAL_MSAA_LOD_NONE                                 0x0
+#define   GC_FEATURES0_SPECIAL_MSAA_LOD_AVAILABLE                            0x1
+
+/* Proper flush is done in fast clear cache. */
+#define GC_FEATURES0_FAST_CLEAR_FLUSH                                      6 : 6
+#define GC_FEATURES0_FAST_CLEAR_FLUSH_End                                      6
+#define GC_FEATURES0_FAST_CLEAR_FLUSH_Start                                    6
+#define GC_FEATURES0_FAST_CLEAR_FLUSH_Type                                   U01
+#define   GC_FEATURES0_FAST_CLEAR_FLUSH_NONE                                 0x0
+#define   GC_FEATURES0_FAST_CLEAR_FLUSH_AVAILABLE                            0x1
+
+/* 2D PE 2.0 is present. */
+#define GC_FEATURES0_2DPE20                                                7 : 7
+#define GC_FEATURES0_2DPE20_End                                                7
+#define GC_FEATURES0_2DPE20_Start                                              7
+#define GC_FEATURES0_2DPE20_Type                                             U01
+#define   GC_FEATURES0_2DPE20_NONE                                           0x0
+#define   GC_FEATURES0_2DPE20_AVAILABLE                                      0x1
+
+/* Reserved. */
+#define GC_FEATURES0_CORRECT_AUTO_DISABLE                                  8 : 8
+#define GC_FEATURES0_CORRECT_AUTO_DISABLE_End                                  8
+#define GC_FEATURES0_CORRECT_AUTO_DISABLE_Start                                8
+#define GC_FEATURES0_CORRECT_AUTO_DISABLE_Type                               U01
+#define   GC_FEATURES0_CORRECT_AUTO_DISABLE_NONE                             0x0
+#define   GC_FEATURES0_CORRECT_AUTO_DISABLE_AVAILABLE                        0x1
+
+/* Supports 8K render target. */
+#define GC_FEATURES0_RENDER_8K                                             9 : 9
+#define GC_FEATURES0_RENDER_8K_End                                             9
+#define GC_FEATURES0_RENDER_8K_Start                                           9
+#define GC_FEATURES0_RENDER_8K_Type                                          U01
+#define   GC_FEATURES0_RENDER_8K_NONE                                        0x0
+#define   GC_FEATURES0_RENDER_8K_AVAILABLE                                   0x1
+
+/* 2 bits are used instead of 4 bits for tile status. */
+#define GC_FEATURES0_TILE_STATUS_2BITS                                   10 : 10
+#define GC_FEATURES0_TILE_STATUS_2BITS_End                                    10
+#define GC_FEATURES0_TILE_STATUS_2BITS_Start                                  10
+#define GC_FEATURES0_TILE_STATUS_2BITS_Type                                  U01
+#define   GC_FEATURES0_TILE_STATUS_2BITS_NONE                                0x0
+#define   GC_FEATURES0_TILE_STATUS_2BITS_AVAILABLE                           0x1
+
+/* Use 2 separate tile status buffers in interleaved mode. */
+#define GC_FEATURES0_SEPARATE_TILE_STATUS_WHEN_INTERLEAVED               11 : 11
+#define GC_FEATURES0_SEPARATE_TILE_STATUS_WHEN_INTERLEAVED_End                11
+#define GC_FEATURES0_SEPARATE_TILE_STATUS_WHEN_INTERLEAVED_Start              11
+#define GC_FEATURES0_SEPARATE_TILE_STATUS_WHEN_INTERLEAVED_Type              U01
+#define   GC_FEATURES0_SEPARATE_TILE_STATUS_WHEN_INTERLEAVED_NONE            0x0
+#define   GC_FEATURES0_SEPARATE_TILE_STATUS_WHEN_INTERLEAVED_AVAILABLE       0x1
+
+/* 32x32 super tile is available. */
+#define GC_FEATURES0_SUPER_TILED_32X32                                   12 : 12
+#define GC_FEATURES0_SUPER_TILED_32X32_End                                    12
+#define GC_FEATURES0_SUPER_TILED_32X32_Start                                  12
+#define GC_FEATURES0_SUPER_TILED_32X32_Type                                  U01
+#define   GC_FEATURES0_SUPER_TILED_32X32_NONE                                0x0
+#define   GC_FEATURES0_SUPER_TILED_32X32_AVAILABLE                           0x1
+
+/* Major updates to VG pipe (TS buffer tiling. State masking.). */
+#define GC_FEATURES0_VG_20                                               13 : 13
+#define GC_FEATURES0_VG_20_End                                                13
+#define GC_FEATURES0_VG_20_Start                                              13
+#define GC_FEATURES0_VG_20_Type                                              U01
+#define   GC_FEATURES0_VG_20_NONE                                            0x0
+#define   GC_FEATURES0_VG_20_AVAILABLE                                       0x1
+
+/* New commands added to the tessellator. */
+#define GC_FEATURES0_TS_EXTENDED_COMMANDS                                14 : 14
+#define GC_FEATURES0_TS_EXTENDED_COMMANDS_End                                 14
+#define GC_FEATURES0_TS_EXTENDED_COMMANDS_Start                               14
+#define GC_FEATURES0_TS_EXTENDED_COMMANDS_Type                               U01
+#define   GC_FEATURES0_TS_EXTENDED_COMMANDS_NONE                             0x0
+#define   GC_FEATURES0_TS_EXTENDED_COMMANDS_AVAILABLE                        0x1
+
+/* If this bit is not set, the FIFO counter should be set to 50.  Else, the   **
+** default should remain.                                                     */
+#define GC_FEATURES0_COMPRESSION_FIFO_FIXED                              15 : 15
+#define GC_FEATURES0_COMPRESSION_FIFO_FIXED_End                               15
+#define GC_FEATURES0_COMPRESSION_FIFO_FIXED_Start                             15
+#define GC_FEATURES0_COMPRESSION_FIFO_FIXED_Type                             U01
+#define   GC_FEATURES0_COMPRESSION_FIFO_FIXED_NONE                           0x0
+#define   GC_FEATURES0_COMPRESSION_FIFO_FIXED_AVAILABLE                      0x1
+
+/* Floor, ceil, and sign instructions are available.  */
+#define GC_FEATURES0_EXTRA_SHADER_INSTRUCTIONS0                          16 : 16
+#define GC_FEATURES0_EXTRA_SHADER_INSTRUCTIONS0_End                           16
+#define GC_FEATURES0_EXTRA_SHADER_INSTRUCTIONS0_Start                         16
+#define GC_FEATURES0_EXTRA_SHADER_INSTRUCTIONS0_Type                         U01
+#define   GC_FEATURES0_EXTRA_SHADER_INSTRUCTIONS0_NONE                       0x0
+#define   GC_FEATURES0_EXTRA_SHADER_INSTRUCTIONS0_AVAILABLE                  0x1
+
+/* VG filter is available.  */
+#define GC_FEATURES0_VG_FILTER                                           17 : 17
+#define GC_FEATURES0_VG_FILTER_End                                            17
+#define GC_FEATURES0_VG_FILTER_Start                                          17
+#define GC_FEATURES0_VG_FILTER_Type                                          U01
+#define   GC_FEATURES0_VG_FILTER_NONE                                        0x0
+#define   GC_FEATURES0_VG_FILTER_AVAILABLE                                   0x1
+
+/* Minor updates to VG pipe (Event generation from VG, TS, PE). Tiled image   **
+** support.                                                                   */
+#define GC_FEATURES0_VG_21                                               18 : 18
+#define GC_FEATURES0_VG_21_End                                                18
+#define GC_FEATURES0_VG_21_Start                                              18
+#define GC_FEATURES0_VG_21_Type                                              U01
+#define   GC_FEATURES0_VG_21_NONE                                            0x0
+#define   GC_FEATURES0_VG_21_AVAILABLE                                       0x1
+
+/* W is sent to SH from RA. */
+#define GC_FEATURES0_SHADER_GETS_W                                       19 : 19
+#define GC_FEATURES0_SHADER_GETS_W_End                                        19
+#define GC_FEATURES0_SHADER_GETS_W_Start                                      19
+#define GC_FEATURES0_SHADER_GETS_W_Type                                      U01
+#define   GC_FEATURES0_SHADER_GETS_W_NONE                                    0x0
+#define   GC_FEATURES0_SHADER_GETS_W_AVAILABLE                               0x1
+
+/* Sqrt, sin, cos instructions are available.  */
+#define GC_FEATURES0_EXTRA_SHADER_INSTRUCTIONS1                          20 : 20
+#define GC_FEATURES0_EXTRA_SHADER_INSTRUCTIONS1_End                           20
+#define GC_FEATURES0_EXTRA_SHADER_INSTRUCTIONS1_Start                         20
+#define GC_FEATURES0_EXTRA_SHADER_INSTRUCTIONS1_Type                         U01
+#define   GC_FEATURES0_EXTRA_SHADER_INSTRUCTIONS1_NONE                       0x0
+#define   GC_FEATURES0_EXTRA_SHADER_INSTRUCTIONS1_AVAILABLE                  0x1
+
+/* Unavailable registers will return 0. */
+#define GC_FEATURES0_DEFAULT_REG0                                        21 : 21
+#define GC_FEATURES0_DEFAULT_REG0_End                                         21
+#define GC_FEATURES0_DEFAULT_REG0_Start                                       21
+#define GC_FEATURES0_DEFAULT_REG0_Type                                       U01
+#define   GC_FEATURES0_DEFAULT_REG0_NONE                                     0x0
+#define   GC_FEATURES0_DEFAULT_REG0_AVAILABLE                                0x1
+
+/* New style MC with separate paths for color and depth. */
+#define GC_FEATURES0_MC_20                                               22 : 22
+#define GC_FEATURES0_MC_20_End                                                22
+#define GC_FEATURES0_MC_20_Start                                              22
+#define GC_FEATURES0_MC_20_Type                                              U01
+#define   GC_FEATURES0_MC_20_NONE                                            0x0
+#define   GC_FEATURES0_MC_20_AVAILABLE                                       0x1
+
+/* Put the MSAA data into sideband fifo. */
+#define GC_FEATURES0_SHADER_MSAA_SIDEBAND                                23 : 23
+#define GC_FEATURES0_SHADER_MSAA_SIDEBAND_End                                 23
+#define GC_FEATURES0_SHADER_MSAA_SIDEBAND_Start                               23
+#define GC_FEATURES0_SHADER_MSAA_SIDEBAND_Type                               U01
+#define   GC_FEATURES0_SHADER_MSAA_SIDEBAND_NONE                             0x0
+#define   GC_FEATURES0_SHADER_MSAA_SIDEBAND_AVAILABLE                        0x1
+
+#define GC_FEATURES0_BUG_FIXES0                                          24 : 24
+#define GC_FEATURES0_BUG_FIXES0_End                                           24
+#define GC_FEATURES0_BUG_FIXES0_Start                                         24
+#define GC_FEATURES0_BUG_FIXES0_Type                                         U01
+#define   GC_FEATURES0_BUG_FIXES0_NONE                                       0x0
+#define   GC_FEATURES0_BUG_FIXES0_AVAILABLE                                  0x1
+
+/* VAA is available or not. */
+#define GC_FEATURES0_VAA                                                 25 : 25
+#define GC_FEATURES0_VAA_End                                                  25
+#define GC_FEATURES0_VAA_Start                                                25
+#define GC_FEATURES0_VAA_Type                                                U01
+#define   GC_FEATURES0_VAA_NONE                                              0x0
+#define   GC_FEATURES0_VAA_AVAILABLE                                         0x1
+
+/* Shader supports bypass mode when MSAA is enabled. */
+#define GC_FEATURES0_BYPASS_IN_MSAA                                      26 : 26
+#define GC_FEATURES0_BYPASS_IN_MSAA_End                                       26
+#define GC_FEATURES0_BYPASS_IN_MSAA_Start                                     26
+#define GC_FEATURES0_BYPASS_IN_MSAA_Type                                     U01
+#define   GC_FEATURES0_BYPASS_IN_MSAA_NONE                                   0x0
+#define   GC_FEATURES0_BYPASS_IN_MSAA_AVAILABLE                              0x1
+
+/* Hierarchiccal Z is supported. */
+#define GC_FEATURES0_HIERARCHICAL_Z                                      27 : 27
+#define GC_FEATURES0_HIERARCHICAL_Z_End                                       27
+#define GC_FEATURES0_HIERARCHICAL_Z_Start                                     27
+#define GC_FEATURES0_HIERARCHICAL_Z_Type                                     U01
+#define   GC_FEATURES0_HIERARCHICAL_Z_NONE                                   0x0
+#define   GC_FEATURES0_HIERARCHICAL_Z_AVAILABLE                              0x1
+
+/* New texture unit is available. */
+#define GC_FEATURES0_NEW_TEXTURE                                         28 : 28
+#define GC_FEATURES0_NEW_TEXTURE_End                                          28
+#define GC_FEATURES0_NEW_TEXTURE_Start                                        28
+#define GC_FEATURES0_NEW_TEXTURE_Type                                        U01
+#define   GC_FEATURES0_NEW_TEXTURE_NONE                                      0x0
+#define   GC_FEATURES0_NEW_TEXTURE_AVAILABLE                                 0x1
+
+/* 2D engine supports A8 target.  */
+#define GC_FEATURES0_A8_TARGET_SUPPORT                                   29 : 29
+#define GC_FEATURES0_A8_TARGET_SUPPORT_End                                    29
+#define GC_FEATURES0_A8_TARGET_SUPPORT_Start                                  29
+#define GC_FEATURES0_A8_TARGET_SUPPORT_Type                                  U01
+#define   GC_FEATURES0_A8_TARGET_SUPPORT_NONE                                0x0
+#define   GC_FEATURES0_A8_TARGET_SUPPORT_AVAILABLE                           0x1
+
+/* Correct stencil behavior in depth only. */
+#define GC_FEATURES0_CORRECT_STENCIL                                     30 : 30
+#define GC_FEATURES0_CORRECT_STENCIL_End                                      30
+#define GC_FEATURES0_CORRECT_STENCIL_Start                                    30
+#define GC_FEATURES0_CORRECT_STENCIL_Type                                    U01
+#define   GC_FEATURES0_CORRECT_STENCIL_NONE                                  0x0
+#define   GC_FEATURES0_CORRECT_STENCIL_AVAILABLE                             0x1
+
+/* Enhance VR and add a mode to walk 16 pixels in 16-bit mode in Vertical     **
+** pass to improve $ hit rate when rotating 90/270.                           */
+#define GC_FEATURES0_ENHANCE_VR                                          31 : 31
+#define GC_FEATURES0_ENHANCE_VR_End                                           31
+#define GC_FEATURES0_ENHANCE_VR_Start                                         31
+#define GC_FEATURES0_ENHANCE_VR_Type                                         U01
+#define   GC_FEATURES0_ENHANCE_VR_NONE                                       0x0
+#define   GC_FEATURES0_ENHANCE_VR_AVAILABLE                                  0x1
+
+union gcfeatures0 {
+	struct {
+		/* GC_FEATURES0_Address:FLIP_Y */
+		unsigned int flipy:1;
+
+		/* GC_FEATURES0_Address:DUAL_RETURN_BUS */
+		unsigned int dualreturnbus:1;
+
+		/* GC_FEATURES0_Address:ENDIANNESS_CONFIG */
+		unsigned int endianessconfig:1;
+
+		/* GC_FEATURES0_Address:TEXTURE8_K */
+		unsigned int texture8k:1;
+
+		/* GC_FEATURES0_Address:CORRECT_TEXTURE_CONVERTER */
+		unsigned int correcttextureconverter:1;
+
+		/* GC_FEATURES0_Address:SPECIAL_MSAA_LOD */
+		unsigned int specialmsaalod:1;
+
+		/* GC_FEATURES0_Address:FAST_CLEAR_FLUSH */
+		unsigned int fastclearflush:1;
+
+		/* GC_FEATURES0_Address:2DPE20 */
+		unsigned int pe2d20:1;
+
+		/* GC_FEATURES0_Address:CORRECT_AUTO_DISABLE */
+		unsigned int correctautodisable:1;
+
+		/* GC_FEATURES0_Address:RENDER_8K */
+		unsigned int render8k:1;
+
+		/* GC_FEATURES0_Address:TILE_STATUS_2BITS */
+		unsigned int tilestatus2bits:1;
+
+		/* GC_FEATURES0_Address:SEPARATE_TILE_STATUS_WHEN_INTERLEAVED */
+		unsigned int separatetilestatus:1;
+
+		/* GC_FEATURES0_Address:SUPER_TILED_32X32 */
+		unsigned int supertiled32x32:1;
+
+		/* GC_FEATURES0_Address:VG_20 */
+		unsigned int vg20:1;
+
+		/* GC_FEATURES0_Address:TS_EXTENDED_COMMANDS */
+		unsigned int tsplus:1;
+
+		/* GC_FEATURES0_Address:COMPRESSION_FIFO_FIXED */
+		unsigned int compressionfifo:1;
+
+		/* GC_FEATURES0_Address:EXTRA_SHADER_INSTRUCTIONS0 */
+		unsigned int shaderinst0:1;
+
+		/* GC_FEATURES0_Address:VG_FILTER */
+		unsigned int vgfilter:1;
+
+		/* GC_FEATURES0_Address:VG_21 */
+		unsigned int vg21:1;
+
+		/* GC_FEATURES0_Address:SHADER_GETS_W */
+		unsigned int shadergetsw:1;
+
+		/* GC_FEATURES0_Address:EXTRA_SHADER_INSTRUCTIONS1 */
+		unsigned int shaderinst1:1;
+
+		/* GC_FEATURES0_Address:DEFAULT_REG0 */
+		unsigned int defaultreg0:1;
+
+		/* GC_FEATURES0_Address:MC_20 */
+		unsigned int mc20:1;
+
+		/* GC_FEATURES0_Address:SHADER_MSAA_SIDEBAND */
+		unsigned int shadermsaasideband:1;
+
+		/* GC_FEATURES0_Address:BUG_FIXES0 */
+		unsigned int bugfixes0:1;
+
+		/* GC_FEATURES0_Address:VAA */
+		unsigned int vaa:1;
+
+		/* GC_FEATURES0_Address:BYPASS_IN_MSAA */
+		unsigned int bypassmsaa:1;
+
+		/* GC_FEATURES0_Address:HIERARCHICAL_Z */
+		unsigned int hz:1;
+
+		/* GC_FEATURES0_Address:NEW_TEXTURE */
+		unsigned int newtx:1;
+
+		/* GC_FEATURES0_Address:A8_TARGET_SUPPORT */
+		unsigned int a8target:1;
+
+		/* GC_FEATURES0_Address:CORRECT_STENCIL */
+		unsigned int correctstencil:1;
+
+		/* GC_FEATURES0_Address:ENHANCE_VR */
+		unsigned int vr20:1;
+	} reg;
+
+	unsigned int raw;
+};
+
+/*******************************************************************************
+** Register GCMinorFeatures1
+*/
+
+/* Shows which features are enabled in this chip. This register has no set
+** reset value. It varies with the implementation.
+*/
+
+#define GC_FEATURES1_Address                                             0x00074
+#define GC_FEATURES1_MSB                                                      15
+#define GC_FEATURES1_LSB                                                       0
+#define GC_FEATURES1_BLK                                                       0
+#define GC_FEATURES1_Count                                                     1
+#define GC_FEATURES1_FieldMask                                        0xFFFFFFFF
+#define GC_FEATURES1_ReadMask                                         0xFFFFFFFF
+#define GC_FEATURES1_WriteMask                                        0x00000000
+#define GC_FEATURES1_ResetValue                                       0x00000000
+
+/* Resolve UV swizzle. */
+#define GC_FEATURES1_RSUV_SWIZZLE                                          0 : 0
+#define GC_FEATURES1_RSUV_SWIZZLE_End                                          0
+#define GC_FEATURES1_RSUV_SWIZZLE_Start                                        0
+#define GC_FEATURES1_RSUV_SWIZZLE_Type                                       U01
+#define   GC_FEATURES1_RSUV_SWIZZLE_NONE                                     0x0
+#define   GC_FEATURES1_RSUV_SWIZZLE_AVAILABLE                                0x1
+
+/* V2 compression. */
+#define GC_FEATURES1_V2_COMPRESSION                                        1 : 1
+#define GC_FEATURES1_V2_COMPRESSION_End                                        1
+#define GC_FEATURES1_V2_COMPRESSION_Start                                      1
+#define GC_FEATURES1_V2_COMPRESSION_Type                                     U01
+#define   GC_FEATURES1_V2_COMPRESSION_NONE                                   0x0
+#define   GC_FEATURES1_V2_COMPRESSION_AVAILABLE                              0x1
+
+/* Double buffering support for VG (second TS-->VG semaphore is present). */
+#define GC_FEATURES1_VG_DOUBLE_BUFFER                                      2 : 2
+#define GC_FEATURES1_VG_DOUBLE_BUFFER_End                                      2
+#define GC_FEATURES1_VG_DOUBLE_BUFFER_Start                                    2
+#define GC_FEATURES1_VG_DOUBLE_BUFFER_Type                                   U01
+#define   GC_FEATURES1_VG_DOUBLE_BUFFER_NONE                                 0x0
+#define   GC_FEATURES1_VG_DOUBLE_BUFFER_AVAILABLE                            0x1
+
+#define GC_FEATURES1_BUG_FIXES1                                            3 : 3
+#define GC_FEATURES1_BUG_FIXES1_End                                            3
+#define GC_FEATURES1_BUG_FIXES1_Start                                          3
+#define GC_FEATURES1_BUG_FIXES1_Type                                         U01
+#define   GC_FEATURES1_BUG_FIXES1_NONE                                       0x0
+#define   GC_FEATURES1_BUG_FIXES1_AVAILABLE                                  0x1
+
+#define GC_FEATURES1_BUG_FIXES2                                            4 : 4
+#define GC_FEATURES1_BUG_FIXES2_End                                            4
+#define GC_FEATURES1_BUG_FIXES2_Start                                          4
+#define GC_FEATURES1_BUG_FIXES2_Type                                         U01
+#define   GC_FEATURES1_BUG_FIXES2_NONE                                       0x0
+#define   GC_FEATURES1_BUG_FIXES2_AVAILABLE                                  0x1
+
+/* Texture has stride and memory addressing. */
+#define GC_FEATURES1_TEXTURE_STRIDE                                        5 : 5
+#define GC_FEATURES1_TEXTURE_STRIDE_End                                        5
+#define GC_FEATURES1_TEXTURE_STRIDE_Start                                      5
+#define GC_FEATURES1_TEXTURE_STRIDE_Type                                     U01
+#define   GC_FEATURES1_TEXTURE_STRIDE_NONE                                   0x0
+#define   GC_FEATURES1_TEXTURE_STRIDE_AVAILABLE                              0x1
+
+#define GC_FEATURES1_BUG_FIXES3                                            6 : 6
+#define GC_FEATURES1_BUG_FIXES3_End                                            6
+#define GC_FEATURES1_BUG_FIXES3_Start                                          6
+#define GC_FEATURES1_BUG_FIXES3_Type                                         U01
+#define   GC_FEATURES1_BUG_FIXES3_NONE                                       0x0
+#define   GC_FEATURES1_BUG_FIXES3_AVAILABLE                                  0x1
+
+#define GC_FEATURES1_CORRECT_AUTO_DISABLE                                  7 : 7
+#define GC_FEATURES1_CORRECT_AUTO_DISABLE_End                                  7
+#define GC_FEATURES1_CORRECT_AUTO_DISABLE_Start                                7
+#define GC_FEATURES1_CORRECT_AUTO_DISABLE_Type                               U01
+#define   GC_FEATURES1_CORRECT_AUTO_DISABLE_NONE                             0x0
+#define   GC_FEATURES1_CORRECT_AUTO_DISABLE_AVAILABLE                        0x1
+
+#define GC_FEATURES1_AUTO_RESTART_TS                                       8 : 8
+#define GC_FEATURES1_AUTO_RESTART_TS_End                                       8
+#define GC_FEATURES1_AUTO_RESTART_TS_Start                                     8
+#define GC_FEATURES1_AUTO_RESTART_TS_Type                                    U01
+#define   GC_FEATURES1_AUTO_RESTART_TS_NONE                                  0x0
+#define   GC_FEATURES1_AUTO_RESTART_TS_AVAILABLE                             0x1
+
+#define GC_FEATURES1_BUG_FIXES4                                            9 : 9
+#define GC_FEATURES1_BUG_FIXES4_End                                            9
+#define GC_FEATURES1_BUG_FIXES4_Start                                          9
+#define GC_FEATURES1_BUG_FIXES4_Type                                         U01
+#define   GC_FEATURES1_BUG_FIXES4_NONE                                       0x0
+#define   GC_FEATURES1_BUG_FIXES4_AVAILABLE                                  0x1
+
+#define GC_FEATURES1_L2_WINDOWING                                        10 : 10
+#define GC_FEATURES1_L2_WINDOWING_End                                         10
+#define GC_FEATURES1_L2_WINDOWING_Start                                       10
+#define GC_FEATURES1_L2_WINDOWING_Type                                       U01
+#define   GC_FEATURES1_L2_WINDOWING_NONE                                     0x0
+#define   GC_FEATURES1_L2_WINDOWING_AVAILABLE                                0x1
+
+#define GC_FEATURES1_HALF_FLOAT_PIPE                                     11 : 11
+#define GC_FEATURES1_HALF_FLOAT_PIPE_End                                      11
+#define GC_FEATURES1_HALF_FLOAT_PIPE_Start                                    11
+#define GC_FEATURES1_HALF_FLOAT_PIPE_Type                                    U01
+#define   GC_FEATURES1_HALF_FLOAT_PIPE_NONE                                  0x0
+#define   GC_FEATURES1_HALF_FLOAT_PIPE_AVAILABLE                             0x1
+
+#define GC_FEATURES1_PIXEL_DITHER                                        12 : 12
+#define GC_FEATURES1_PIXEL_DITHER_End                                         12
+#define GC_FEATURES1_PIXEL_DITHER_Start                                       12
+#define GC_FEATURES1_PIXEL_DITHER_Type                                       U01
+#define   GC_FEATURES1_PIXEL_DITHER_NONE                                     0x0
+#define   GC_FEATURES1_PIXEL_DITHER_AVAILABLE                                0x1
+
+#define GC_FEATURES1_TWO_STENCIL_REFERENCE                               13 : 13
+#define GC_FEATURES1_TWO_STENCIL_REFERENCE_End                                13
+#define GC_FEATURES1_TWO_STENCIL_REFERENCE_Start                              13
+#define GC_FEATURES1_TWO_STENCIL_REFERENCE_Type                              U01
+#define   GC_FEATURES1_TWO_STENCIL_REFERENCE_NONE                            0x0
+#define   GC_FEATURES1_TWO_STENCIL_REFERENCE_AVAILABLE                       0x1
+
+#define GC_FEATURES1_EXTENDED_PIXEL_FORMAT                               14 : 14
+#define GC_FEATURES1_EXTENDED_PIXEL_FORMAT_End                                14
+#define GC_FEATURES1_EXTENDED_PIXEL_FORMAT_Start                              14
+#define GC_FEATURES1_EXTENDED_PIXEL_FORMAT_Type                              U01
+#define   GC_FEATURES1_EXTENDED_PIXEL_FORMAT_NONE                            0x0
+#define   GC_FEATURES1_EXTENDED_PIXEL_FORMAT_AVAILABLE                       0x1
+
+/* EEZ and HZ are correct. */
+#define GC_FEATURES1_CORRECT_MIN_MAX_DEPTH                               15 : 15
+#define GC_FEATURES1_CORRECT_MIN_MAX_DEPTH_End                                15
+#define GC_FEATURES1_CORRECT_MIN_MAX_DEPTH_Start                              15
+#define GC_FEATURES1_CORRECT_MIN_MAX_DEPTH_Type                              U01
+#define   GC_FEATURES1_CORRECT_MIN_MAX_DEPTH_NONE                            0x0
+#define   GC_FEATURES1_CORRECT_MIN_MAX_DEPTH_AVAILABLE                       0x1
+
+/* Dither and filter+alpha available. */
+#define GC_FEATURES1_DITHER_AND_FILTER_PLUS_ALPHA_2D                     16 : 16
+#define GC_FEATURES1_DITHER_AND_FILTER_PLUS_ALPHA_2D_End                      16
+#define GC_FEATURES1_DITHER_AND_FILTER_PLUS_ALPHA_2D_Start                    16
+#define GC_FEATURES1_DITHER_AND_FILTER_PLUS_ALPHA_2D_Type                    U01
+#define   GC_FEATURES1_DITHER_AND_FILTER_PLUS_ALPHA_2D_NONE                  0x0
+#define   GC_FEATURES1_DITHER_AND_FILTER_PLUS_ALPHA_2D_AVAILABLE             0x1
+
+#define GC_FEATURES1_BUG_FIXES5                                          17 : 17
+#define GC_FEATURES1_BUG_FIXES5_End                                           17
+#define GC_FEATURES1_BUG_FIXES5_Start                                         17
+#define GC_FEATURES1_BUG_FIXES5_Type                                         U01
+#define   GC_FEATURES1_BUG_FIXES5_NONE                                       0x0
+#define   GC_FEATURES1_BUG_FIXES5_AVAILABLE                                  0x1
+
+#define GC_FEATURES1_NEW_2D                                              18 : 18
+#define GC_FEATURES1_NEW_2D_End                                               18
+#define GC_FEATURES1_NEW_2D_Start                                             18
+#define GC_FEATURES1_NEW_2D_Type                                             U01
+#define   GC_FEATURES1_NEW_2D_NONE                                           0x0
+#define   GC_FEATURES1_NEW_2D_AVAILABLE                                      0x1
+
+#define GC_FEATURES1_NEW_FLOATING_POINT_ARITHMETIC                       19 : 19
+#define GC_FEATURES1_NEW_FLOATING_POINT_ARITHMETIC_End                        19
+#define GC_FEATURES1_NEW_FLOATING_POINT_ARITHMETIC_Start                      19
+#define GC_FEATURES1_NEW_FLOATING_POINT_ARITHMETIC_Type                      U01
+#define   GC_FEATURES1_NEW_FLOATING_POINT_ARITHMETIC_NONE                    0x0
+#define   GC_FEATURES1_NEW_FLOATING_POINT_ARITHMETIC_AVAILABLE               0x1
+
+#define GC_FEATURES1_TEXTURE_HORIZONTAL_ALIGNMENT_SELECT                 20 : 20
+#define GC_FEATURES1_TEXTURE_HORIZONTAL_ALIGNMENT_SELECT_End                  20
+#define GC_FEATURES1_TEXTURE_HORIZONTAL_ALIGNMENT_SELECT_Start                20
+#define GC_FEATURES1_TEXTURE_HORIZONTAL_ALIGNMENT_SELECT_Type                U01
+#define   GC_FEATURES1_TEXTURE_HORIZONTAL_ALIGNMENT_SELECT_NONE              0x0
+#define   GC_FEATURES1_TEXTURE_HORIZONTAL_ALIGNMENT_SELECT_AVAILABLE         0x1
+
+#define GC_FEATURES1_NON_POWER_OF_TWO                                    21 : 21
+#define GC_FEATURES1_NON_POWER_OF_TWO_End                                     21
+#define GC_FEATURES1_NON_POWER_OF_TWO_Start                                   21
+#define GC_FEATURES1_NON_POWER_OF_TWO_Type                                   U01
+#define   GC_FEATURES1_NON_POWER_OF_TWO_NONE                                 0x0
+#define   GC_FEATURES1_NON_POWER_OF_TWO_AVAILABLE                            0x1
+
+#define GC_FEATURES1_LINEAR_TEXTURE_SUPPORT                              22 : 22
+#define GC_FEATURES1_LINEAR_TEXTURE_SUPPORT_End                               22
+#define GC_FEATURES1_LINEAR_TEXTURE_SUPPORT_Start                             22
+#define GC_FEATURES1_LINEAR_TEXTURE_SUPPORT_Type                             U01
+#define   GC_FEATURES1_LINEAR_TEXTURE_SUPPORT_NONE                           0x0
+#define   GC_FEATURES1_LINEAR_TEXTURE_SUPPORT_AVAILABLE                      0x1
+
+#define GC_FEATURES1_HALTI0                                              23 : 23
+#define GC_FEATURES1_HALTI0_End                                               23
+#define GC_FEATURES1_HALTI0_Start                                             23
+#define GC_FEATURES1_HALTI0_Type                                             U01
+#define   GC_FEATURES1_HALTI0_NONE                                           0x0
+#define   GC_FEATURES1_HALTI0_AVAILABLE                                      0x1
+
+#define GC_FEATURES1_CORRECT_OVERFLOW_VG                                 24 : 24
+#define GC_FEATURES1_CORRECT_OVERFLOW_VG_End                                  24
+#define GC_FEATURES1_CORRECT_OVERFLOW_VG_Start                                24
+#define GC_FEATURES1_CORRECT_OVERFLOW_VG_Type                                U01
+#define   GC_FEATURES1_CORRECT_OVERFLOW_VG_NONE                              0x0
+#define   GC_FEATURES1_CORRECT_OVERFLOW_VG_AVAILABLE                         0x1
+
+#define GC_FEATURES1_NEGATIVE_LOG_FIX                                    25 : 25
+#define GC_FEATURES1_NEGATIVE_LOG_FIX_End                                     25
+#define GC_FEATURES1_NEGATIVE_LOG_FIX_Start                                   25
+#define GC_FEATURES1_NEGATIVE_LOG_FIX_Type                                   U01
+#define   GC_FEATURES1_NEGATIVE_LOG_FIX_NONE                                 0x0
+#define   GC_FEATURES1_NEGATIVE_LOG_FIX_AVAILABLE                            0x1
+
+#define GC_FEATURES1_RESOLVE_OFFSET                                      26 : 26
+#define GC_FEATURES1_RESOLVE_OFFSET_End                                       26
+#define GC_FEATURES1_RESOLVE_OFFSET_Start                                     26
+#define GC_FEATURES1_RESOLVE_OFFSET_Type                                     U01
+#define   GC_FEATURES1_RESOLVE_OFFSET_NONE                                   0x0
+#define   GC_FEATURES1_RESOLVE_OFFSET_AVAILABLE                              0x1
+
+#define GC_FEATURES1_OK_TO_GATE_AXI_CLOCK                                27 : 27
+#define GC_FEATURES1_OK_TO_GATE_AXI_CLOCK_End                                 27
+#define GC_FEATURES1_OK_TO_GATE_AXI_CLOCK_Start                               27
+#define GC_FEATURES1_OK_TO_GATE_AXI_CLOCK_Type                               U01
+#define   GC_FEATURES1_OK_TO_GATE_AXI_CLOCK_NONE                             0x0
+#define   GC_FEATURES1_OK_TO_GATE_AXI_CLOCK_AVAILABLE                        0x1
+
+#define GC_FEATURES1_MMU                                                 28 : 28
+#define GC_FEATURES1_MMU_End                                                  28
+#define GC_FEATURES1_MMU_Start                                                28
+#define GC_FEATURES1_MMU_Type                                                U01
+#define   GC_FEATURES1_MMU_NONE                                              0x0
+#define   GC_FEATURES1_MMU_AVAILABLE                                         0x1
+
+#define GC_FEATURES1_WIDE_LINE                                           29 : 29
+#define GC_FEATURES1_WIDE_LINE_End                                            29
+#define GC_FEATURES1_WIDE_LINE_Start                                          29
+#define GC_FEATURES1_WIDE_LINE_Type                                          U01
+#define   GC_FEATURES1_WIDE_LINE_NONE                                        0x0
+#define   GC_FEATURES1_WIDE_LINE_AVAILABLE                                   0x1
+
+#define GC_FEATURES1_BUG_FIXES6                                          30 : 30
+#define GC_FEATURES1_BUG_FIXES6_End                                           30
+#define GC_FEATURES1_BUG_FIXES6_Start                                         30
+#define GC_FEATURES1_BUG_FIXES6_Type                                         U01
+#define   GC_FEATURES1_BUG_FIXES6_NONE                                       0x0
+#define   GC_FEATURES1_BUG_FIXES6_AVAILABLE                                  0x1
+
+#define GC_FEATURES1_FC_FLUSH_STALL                                      31 : 31
+#define GC_FEATURES1_FC_FLUSH_STALL_End                                       31
+#define GC_FEATURES1_FC_FLUSH_STALL_Start                                     31
+#define GC_FEATURES1_FC_FLUSH_STALL_Type                                     U01
+#define   GC_FEATURES1_FC_FLUSH_STALL_NONE                                   0x0
+#define   GC_FEATURES1_FC_FLUSH_STALL_AVAILABLE                              0x1
+
+union gcfeatures1 {
+	struct {
+		/* GC_FEATURES1_Address:RSUV_SWIZZLE */
+		unsigned int rsuvswizzle:1;
+
+		/* GC_FEATURES1_Address:V2_COMPRESSION */
+		unsigned int v2compression:1;
+
+		/* GC_FEATURES1_Address:VG_DOUBLE_BUFFER */
+		unsigned int vgdblbuffer:1;
+
+		/* GC_FEATURES1_Address:BUG_FIXES1 */
+		unsigned int bugfixes1:1;
+
+		/* GC_FEATURES1_Address:BUG_FIXES2 */
+		unsigned int bugfixes2:1;
+
+		/* GC_FEATURES1_Address:TEXTURE_STRIDE */
+		unsigned int txstride:1;
+
+		/* GC_FEATURES1_Address:BUG_FIXES3 */
+		unsigned int bugfixes3:1;
+
+		/* GC_FEATURES1_Address:CORRECT_AUTO_DISABLE */
+		unsigned int correctautodisable:1;
+
+		/* GC_FEATURES1_Address:AUTO_RESTART_TS */
+		unsigned int autorestartts:1;
+
+		/* GC_FEATURES1_Address:BUG_FIXES4 */
+		unsigned int bugfixes4:1;
+
+		/* GC_FEATURES1_Address:L2_WINDOWING */
+		unsigned int l2win:1;
+
+		/* GC_FEATURES1_Address:HALF_FLOAT_PIPE */
+		unsigned int halffloatpipe:1;
+
+		/* GC_FEATURES1_Address:PIXEL_DITHER */
+		unsigned int pixeldither:1;
+
+		/* GC_FEATURES1_Address:TWO_STENCIL_REFERENCE */
+		unsigned int twostencilref:1;
+
+		/* GC_FEATURES1_Address:EXTENDED_PIXEL_FORMAT */
+		unsigned int pixformatex:1;
+
+		/* GC_FEATURES1_Address:CORRECT_MIN_MAX_DEPTH */
+		unsigned int correctminmaxdepth:1;
+
+		/* GC_FEATURES1_Address:DITHER_AND_FILTER_PLUS_ALPHA_2D */
+		unsigned int ditherfilter:1;
+
+		/* GC_FEATURES1_Address:BUG_FIXES5 */
+		unsigned int bugfixes5:1;
+
+		/* GC_FEATURES1_Address:NEW_2D */
+		unsigned int new2d:1;
+
+		/* GC_FEATURES1_Address:NEW_FLOATING_POINT_ARITHMETIC */
+		unsigned int newfp:1;
+
+		/* GC_FEATURES1_Address:TEXTURE_HORIZONTAL_ALIGNMENT_SELECT */
+		unsigned int txalign:1;
+
+		/* GC_FEATURES1_Address:NON_POWER_OF_TWO */
+		unsigned int nonpowof2:1;
+
+		/* GC_FEATURES1_Address:LINEAR_TEXTURE_SUPPORT */
+		unsigned int lineartx:1;
+
+		/* GC_FEATURES1_Address:HALTI0 */
+		unsigned int halti0:1;
+
+		/* GC_FEATURES1_Address:CORRECT_OVERFLOW_VG */
+		unsigned int correctoverflowvg:1;
+
+		/* GC_FEATURES1_Address:NEGATIVE_LOG_FIX */
+		unsigned int neglogfix:1;
+
+		/* GC_FEATURES1_Address:RESOLVE_OFFSET */
+		unsigned int rsoffset:1;
+
+		/* GC_FEATURES1_Address:OK_TO_GATE_AXI_CLOCK */
+		unsigned int axiclockgating:1;
+
+		/* GC_FEATURES1_Address:MMU */
+		unsigned int mmu:1;
+
+		/* GC_FEATURES1_Address:WIDE_LINE */
+		unsigned int wideline:1;
+
+		/* GC_FEATURES1_Address:BUG_FIXES6 */
+		unsigned int bugfixes6:1;
+
+		/* GC_FEATURES1_Address:FC_FLUSH_STALL */
+		unsigned int fcflushstall:1;
+	} reg;
+
+	unsigned int raw;
+};
+
+/*******************************************************************************
+** Register GCMinorFeatures2
+*/
+
+/* Shows which features are enabled in this chip. This register has no set    **
+** reset value. It varies with the implementation.                            */
+
+#define GC_FEATURES2_Address                                             0x00084
+#define GC_FEATURES2_MSB                                                      15
+#define GC_FEATURES2_LSB                                                       0
+#define GC_FEATURES2_BLK                                                       0
+#define GC_FEATURES2_Count                                                     1
+#define GC_FEATURES2_FieldMask                                        0xFFFFFFFF
+#define GC_FEATURES2_ReadMask                                         0xFFFFFFFF
+#define GC_FEATURES2_WriteMask                                        0x00000000
+#define GC_FEATURES2_ResetValue                                       0x00000000
+
+#define GC_FEATURES2_LINE_LOOP                                             0 : 0
+#define GC_FEATURES2_LINE_LOOP_End                                             0
+#define GC_FEATURES2_LINE_LOOP_Start                                           0
+#define GC_FEATURES2_LINE_LOOP_Type                                          U01
+#define   GC_FEATURES2_LINE_LOOP_NONE                                        0x0
+#define   GC_FEATURES2_LINE_LOOP_AVAILABLE                                   0x1
+
+#define GC_FEATURES2_LOGIC_OP                                              1 : 1
+#define GC_FEATURES2_LOGIC_OP_End                                              1
+#define GC_FEATURES2_LOGIC_OP_Start                                            1
+#define GC_FEATURES2_LOGIC_OP_Type                                           U01
+#define   GC_FEATURES2_LOGIC_OP_NONE                                         0x0
+#define   GC_FEATURES2_LOGIC_OP_AVAILABLE                                    0x1
+
+#define GC_FEATURES2_SEAMLESS_CUBE_MAP                                     2 : 2
+#define GC_FEATURES2_SEAMLESS_CUBE_MAP_End                                     2
+#define GC_FEATURES2_SEAMLESS_CUBE_MAP_Start                                   2
+#define GC_FEATURES2_SEAMLESS_CUBE_MAP_Type                                  U01
+#define   GC_FEATURES2_SEAMLESS_CUBE_MAP_NONE                                0x0
+#define   GC_FEATURES2_SEAMLESS_CUBE_MAP_AVAILABLE                           0x1
+
+#define GC_FEATURES2_SUPER_TILED_TEXTURE                                   3 : 3
+#define GC_FEATURES2_SUPER_TILED_TEXTURE_End                                   3
+#define GC_FEATURES2_SUPER_TILED_TEXTURE_Start                                 3
+#define GC_FEATURES2_SUPER_TILED_TEXTURE_Type                                U01
+#define   GC_FEATURES2_SUPER_TILED_TEXTURE_NONE                              0x0
+#define   GC_FEATURES2_SUPER_TILED_TEXTURE_AVAILABLE                         0x1
+
+#define GC_FEATURES2_LINEAR_PE                                             4 : 4
+#define GC_FEATURES2_LINEAR_PE_End                                             4
+#define GC_FEATURES2_LINEAR_PE_Start                                           4
+#define GC_FEATURES2_LINEAR_PE_Type                                          U01
+#define   GC_FEATURES2_LINEAR_PE_NONE                                        0x0
+#define   GC_FEATURES2_LINEAR_PE_AVAILABLE                                   0x1
+
+#define GC_FEATURES2_RECT_PRIMITIVE                                        5 : 5
+#define GC_FEATURES2_RECT_PRIMITIVE_End                                        5
+#define GC_FEATURES2_RECT_PRIMITIVE_Start                                      5
+#define GC_FEATURES2_RECT_PRIMITIVE_Type                                     U01
+#define   GC_FEATURES2_RECT_PRIMITIVE_NONE                                   0x0
+#define   GC_FEATURES2_RECT_PRIMITIVE_AVAILABLE                              0x1
+
+#define GC_FEATURES2_COMPOSITION                                           6 : 6
+#define GC_FEATURES2_COMPOSITION_End                                           6
+#define GC_FEATURES2_COMPOSITION_Start                                         6
+#define GC_FEATURES2_COMPOSITION_Type                                        U01
+#define   GC_FEATURES2_COMPOSITION_NONE                                      0x0
+#define   GC_FEATURES2_COMPOSITION_AVAILABLE                                 0x1
+
+#define GC_FEATURES2_CORRECT_AUTO_DISABLE_COUNT_WIDTH                      7 : 7
+#define GC_FEATURES2_CORRECT_AUTO_DISABLE_COUNT_WIDTH_End                      7
+#define GC_FEATURES2_CORRECT_AUTO_DISABLE_COUNT_WIDTH_Start                    7
+#define GC_FEATURES2_CORRECT_AUTO_DISABLE_COUNT_WIDTH_Type                   U01
+#define   GC_FEATURES2_CORRECT_AUTO_DISABLE_COUNT_WIDTH_NONE                 0x0
+#define   GC_FEATURES2_CORRECT_AUTO_DISABLE_COUNT_WIDTH_AVAILABLE            0x1
+
+#define GC_FEATURES2_PE_SWIZZLE                                            8 : 8
+#define GC_FEATURES2_PE_SWIZZLE_End                                            8
+#define GC_FEATURES2_PE_SWIZZLE_Start                                          8
+#define GC_FEATURES2_PE_SWIZZLE_Type                                         U01
+#define   GC_FEATURES2_PE_SWIZZLE_NONE                                       0x0
+#define   GC_FEATURES2_PE_SWIZZLE_AVAILABLE                                  0x1
+
+#define GC_FEATURES2_END_EVENT                                             9 : 9
+#define GC_FEATURES2_END_EVENT_End                                             9
+#define GC_FEATURES2_END_EVENT_Start                                           9
+#define GC_FEATURES2_END_EVENT_Type                                          U01
+#define   GC_FEATURES2_END_EVENT_NONE                                        0x0
+#define   GC_FEATURES2_END_EVENT_AVAILABLE                                   0x1
+
+#define GC_FEATURES2_S1S8                                                10 : 10
+#define GC_FEATURES2_S1S8_End                                                 10
+#define GC_FEATURES2_S1S8_Start                                               10
+#define GC_FEATURES2_S1S8_Type                                               U01
+#define   GC_FEATURES2_S1S8_NONE                                             0x0
+#define   GC_FEATURES2_S1S8_AVAILABLE                                        0x1
+
+#define GC_FEATURES2_HALTI1                                              11 : 11
+#define GC_FEATURES2_HALTI1_End                                               11
+#define GC_FEATURES2_HALTI1_Start                                             11
+#define GC_FEATURES2_HALTI1_Type                                             U01
+#define   GC_FEATURES2_HALTI1_NONE                                           0x0
+#define   GC_FEATURES2_HALTI1_AVAILABLE                                      0x1
+
+#define GC_FEATURES2_RGB888                                              12 : 12
+#define GC_FEATURES2_RGB888_End                                               12
+#define GC_FEATURES2_RGB888_Start                                             12
+#define GC_FEATURES2_RGB888_Type                                             U01
+#define   GC_FEATURES2_RGB888_NONE                                           0x0
+#define   GC_FEATURES2_RGB888_AVAILABLE                                      0x1
+
+#define GC_FEATURES2_TX__YUV_ASSEMBLER                                   13 : 13
+#define GC_FEATURES2_TX__YUV_ASSEMBLER_End                                    13
+#define GC_FEATURES2_TX__YUV_ASSEMBLER_Start                                  13
+#define GC_FEATURES2_TX__YUV_ASSEMBLER_Type                                  U01
+#define   GC_FEATURES2_TX__YUV_ASSEMBLER_NONE                                0x0
+#define   GC_FEATURES2_TX__YUV_ASSEMBLER_AVAILABLE                           0x1
+
+#define GC_FEATURES2_DYNAMIC_FREQUENCY_SCALING                           14 : 14
+#define GC_FEATURES2_DYNAMIC_FREQUENCY_SCALING_End                            14
+#define GC_FEATURES2_DYNAMIC_FREQUENCY_SCALING_Start                          14
+#define GC_FEATURES2_DYNAMIC_FREQUENCY_SCALING_Type                          U01
+#define   GC_FEATURES2_DYNAMIC_FREQUENCY_SCALING_NONE                        0x0
+#define   GC_FEATURES2_DYNAMIC_FREQUENCY_SCALING_AVAILABLE                   0x1
+
+#define GC_FEATURES2_TX_FILTER                                           15 : 15
+#define GC_FEATURES2_TX_FILTER_End                                            15
+#define GC_FEATURES2_TX_FILTER_Start                                          15
+#define GC_FEATURES2_TX_FILTER_Type                                          U01
+#define   GC_FEATURES2_TX_FILTER_NONE                                        0x0
+#define   GC_FEATURES2_TX_FILTER_AVAILABLE                                   0x1
+
+#define GC_FEATURES2_FULL_DIRECT_FB                                      16 : 16
+#define GC_FEATURES2_FULL_DIRECT_FB_End                                       16
+#define GC_FEATURES2_FULL_DIRECT_FB_Start                                     16
+#define GC_FEATURES2_FULL_DIRECT_FB_Type                                     U01
+#define   GC_FEATURES2_FULL_DIRECT_FB_NONE                                   0x0
+#define   GC_FEATURES2_FULL_DIRECT_FB_AVAILABLE                              0x1
+
+#define GC_FEATURES2_ONE_PASS_2D_FILTER                                  17 : 17
+#define GC_FEATURES2_ONE_PASS_2D_FILTER_End                                   17
+#define GC_FEATURES2_ONE_PASS_2D_FILTER_Start                                 17
+#define GC_FEATURES2_ONE_PASS_2D_FILTER_Type                                 U01
+#define   GC_FEATURES2_ONE_PASS_2D_FILTER_NONE                               0x0
+#define   GC_FEATURES2_ONE_PASS_2D_FILTER_AVAILABLE                          0x1
+
+#define GC_FEATURES2_THREAD_WALKER_IN_PS                                 18 : 18
+#define GC_FEATURES2_THREAD_WALKER_IN_PS_End                                  18
+#define GC_FEATURES2_THREAD_WALKER_IN_PS_Start                                18
+#define GC_FEATURES2_THREAD_WALKER_IN_PS_Type                                U01
+#define   GC_FEATURES2_THREAD_WALKER_IN_PS_NONE                              0x0
+#define   GC_FEATURES2_THREAD_WALKER_IN_PS_AVAILABLE                         0x1
+
+#define GC_FEATURES2_TILE_FILLER                                         19 : 19
+#define GC_FEATURES2_TILE_FILLER_End                                          19
+#define GC_FEATURES2_TILE_FILLER_Start                                        19
+#define GC_FEATURES2_TILE_FILLER_Type                                        U01
+#define   GC_FEATURES2_TILE_FILLER_NONE                                      0x0
+#define   GC_FEATURES2_TILE_FILLER_AVAILABLE                                 0x1
+
+#define GC_FEATURES2_YUV_STANDARD                                        20 : 20
+#define GC_FEATURES2_YUV_STANDARD_End                                         20
+#define GC_FEATURES2_YUV_STANDARD_Start                                       20
+#define GC_FEATURES2_YUV_STANDARD_Type                                       U01
+#define   GC_FEATURES2_YUV_STANDARD_NONE                                     0x0
+#define   GC_FEATURES2_YUV_STANDARD_AVAILABLE                                0x1
+
+#define GC_FEATURES2_MULTI_SOURCE_BLT                                    21 : 21
+#define GC_FEATURES2_MULTI_SOURCE_BLT_End                                     21
+#define GC_FEATURES2_MULTI_SOURCE_BLT_Start                                   21
+#define GC_FEATURES2_MULTI_SOURCE_BLT_Type                                   U01
+#define   GC_FEATURES2_MULTI_SOURCE_BLT_NONE                                 0x0
+#define   GC_FEATURES2_MULTI_SOURCE_BLT_AVAILABLE                            0x1
+
+#define GC_FEATURES2_YUV_CONVERSION                                      22 : 22
+#define GC_FEATURES2_YUV_CONVERSION_End                                       22
+#define GC_FEATURES2_YUV_CONVERSION_Start                                     22
+#define GC_FEATURES2_YUV_CONVERSION_Type                                     U01
+#define   GC_FEATURES2_YUV_CONVERSION_NONE                                   0x0
+#define   GC_FEATURES2_YUV_CONVERSION_AVAILABLE                              0x1
+
+#define GC_FEATURES2_FLUSH_FIXED_2D                                      23 : 23
+#define GC_FEATURES2_FLUSH_FIXED_2D_End                                       23
+#define GC_FEATURES2_FLUSH_FIXED_2D_Start                                     23
+#define GC_FEATURES2_FLUSH_FIXED_2D_Type                                     U01
+#define   GC_FEATURES2_FLUSH_FIXED_2D_NONE                                   0x0
+#define   GC_FEATURES2_FLUSH_FIXED_2D_AVAILABLE                              0x1
+
+#define GC_FEATURES2_INTERLEAVER                                         24 : 24
+#define GC_FEATURES2_INTERLEAVER_End                                          24
+#define GC_FEATURES2_INTERLEAVER_Start                                        24
+#define GC_FEATURES2_INTERLEAVER_Type                                        U01
+#define   GC_FEATURES2_INTERLEAVER_NONE                                      0x0
+#define   GC_FEATURES2_INTERLEAVER_AVAILABLE                                 0x1
+
+#define GC_FEATURES2_MIXED_STREAMS                                       25 : 25
+#define GC_FEATURES2_MIXED_STREAMS_End                                        25
+#define GC_FEATURES2_MIXED_STREAMS_Start                                      25
+#define GC_FEATURES2_MIXED_STREAMS_Type                                      U01
+#define   GC_FEATURES2_MIXED_STREAMS_NONE                                    0x0
+#define   GC_FEATURES2_MIXED_STREAMS_AVAILABLE                               0x1
+
+#define GC_FEATURES2_L2_CACHE_FOR_2D_420                                 26 : 26
+#define GC_FEATURES2_L2_CACHE_FOR_2D_420_End                                  26
+#define GC_FEATURES2_L2_CACHE_FOR_2D_420_Start                                26
+#define GC_FEATURES2_L2_CACHE_FOR_2D_420_Type                                U01
+#define   GC_FEATURES2_L2_CACHE_FOR_2D_420_NONE                              0x0
+#define   GC_FEATURES2_L2_CACHE_FOR_2D_420_AVAILABLE                         0x1
+
+#define GC_FEATURES2_BUG_FIXES7                                          27 : 27
+#define GC_FEATURES2_BUG_FIXES7_End                                           27
+#define GC_FEATURES2_BUG_FIXES7_Start                                         27
+#define GC_FEATURES2_BUG_FIXES7_Type                                         U01
+#define   GC_FEATURES2_BUG_FIXES7_NONE                                       0x0
+#define   GC_FEATURES2_BUG_FIXES7_AVAILABLE                                  0x1
+
+#define GC_FEATURES2_NO_INDEX_PATTERN                                    28 : 28
+#define GC_FEATURES2_NO_INDEX_PATTERN_End                                     28
+#define GC_FEATURES2_NO_INDEX_PATTERN_Start                                   28
+#define GC_FEATURES2_NO_INDEX_PATTERN_Type                                   U01
+#define   GC_FEATURES2_NO_INDEX_PATTERN_NONE                                 0x0
+#define   GC_FEATURES2_NO_INDEX_PATTERN_AVAILABLE                            0x1
+
+#define GC_FEATURES2_TEXTURE_TILE_STATUS                                 29 : 29
+#define GC_FEATURES2_TEXTURE_TILE_STATUS_End                                  29
+#define GC_FEATURES2_TEXTURE_TILE_STATUS_Start                                29
+#define GC_FEATURES2_TEXTURE_TILE_STATUS_Type                                U01
+#define   GC_FEATURES2_TEXTURE_TILE_STATUS_NONE                              0x0
+#define   GC_FEATURES2_TEXTURE_TILE_STATUS_AVAILABLE                         0x1
+
+#define GC_FEATURES2_DECOMPRESS_Z16                                      30 : 30
+#define GC_FEATURES2_DECOMPRESS_Z16_End                                       30
+#define GC_FEATURES2_DECOMPRESS_Z16_Start                                     30
+#define GC_FEATURES2_DECOMPRESS_Z16_Type                                     U01
+#define   GC_FEATURES2_DECOMPRESS_Z16_NONE                                   0x0
+#define   GC_FEATURES2_DECOMPRESS_Z16_AVAILABLE                              0x1
+
+#define GC_FEATURES2_BUG_FIXES8                                          31 : 31
+#define GC_FEATURES2_BUG_FIXES8_End                                           31
+#define GC_FEATURES2_BUG_FIXES8_Start                                         31
+#define GC_FEATURES2_BUG_FIXES8_Type                                         U01
+#define   GC_FEATURES2_BUG_FIXES8_NONE                                       0x0
+#define   GC_FEATURES2_BUG_FIXES8_AVAILABLE                                  0x1
+
+union gcfeatures2 {
+	struct {
+		/* GC_FEATURES2_Address:LINE_LOOP */
+		unsigned int lineloop:1;
+
+		/* GC_FEATURES2_Address:LOGIC_OP */
+		unsigned int logop:1;
+
+		/* GC_FEATURES2_Address:SEAMLESS_CUBE_MAP */
+		unsigned int cubemap:1;
+
+		/* GC_FEATURES2_Address:SUPER_TILED_TEXTURE */
+		unsigned int supertiledtx:1;
+
+		/* GC_FEATURES2_Address:LINEAR_PE */
+		unsigned int linearpe:1;
+
+		/* GC_FEATURES2_Address:RECT_PRIMITIVE */
+		unsigned int rectprim:1;
+
+		/* GC_FEATURES2_Address:COMPOSITION */
+		unsigned int composition:1;
+
+		/* GC_FEATURES2_Address:CORRECT_AUTO_DISABLE_COUNT_WIDTH */
+		unsigned int correctcountwidth:1;
+
+		/* GC_FEATURES2_Address:PE_SWIZZLE */
+		unsigned int peswizzle:1;
+
+		/* GC_FEATURES2_Address:END_EVENT */
+		unsigned int endevent:1;
+
+		/* GC_FEATURES2_Address:S1S8 */
+		unsigned int s1s8:1;
+
+		/* GC_FEATURES2_Address:HALTI1 */
+		unsigned int halti1:1;
+
+		/* GC_FEATURES2_Address:RGB888 */
+		unsigned int rgb888:1;
+
+		/* GC_FEATURES2_Address:TX__YUV_ASSEMBLER */
+		unsigned int txyuvasm:1;
+
+		/* GC_FEATURES2_Address:DYNAMIC_FREQUENCY_SCALING */
+		unsigned int dynscaling:1;
+
+		/* GC_FEATURES2_Address:TX_FILTER */
+		unsigned int txfilter:1;
+
+		/* GC_FEATURES2_Address:FULL_DIRECT_FB */
+		unsigned int dfb:1;
+
+		/* GC_FEATURES2_Address:ONE_PASS_2D_FILTER */
+		unsigned int onepassfilter:1;
+
+		/* GC_FEATURES2_Address:THREAD_WALKER_IN_PS */
+		unsigned int pstw:1;
+
+		/* GC_FEATURES2_Address:TILE_FILLER */
+		unsigned int tilefiller:1;
+
+		/* GC_FEATURES2_Address:YUV_STANDARD */
+		unsigned int yuvstd:1;
+
+		/* GC_FEATURES2_Address:MULTI_SOURCE_BLT */
+		unsigned int multisrc:1;
+
+		/* GC_FEATURES2_Address:YUV_CONVERSION */
+		unsigned int yuvconvert:1;
+
+		/* GC_FEATURES2_Address:FLUSH_FIXED_2D */
+		unsigned int flushfixed2d:1;
+
+		/* GC_FEATURES2_Address:INTERLEAVER */
+		unsigned int interleaver:1;
+
+		/* GC_FEATURES2_Address:MIXED_STREAMS */
+		unsigned int mixedstreams:1;
+
+		/* GC_FEATURES2_Address:L2_CACHE_FOR_2D_420 */
+		unsigned int l2cachefor420:1;
+
+		/* GC_FEATURES2_Address:BUG_FIXES7 */
+		unsigned int bugfixes7:1;
+
+		/* GC_FEATURES2_Address:NO_INDEX_PATTERN */
+		unsigned int noindexpatern:1;
+
+		/* GC_FEATURES2_Address:TEXTURE_TILE_STATUS */
+		unsigned int tilestatustx:1;
+
+		/* GC_FEATURES2_Address:DECOMPRESS_Z16 */
+		unsigned int decompressz16:1;
+
+		/* GC_FEATURES2_Address:BUG_FIXES8 */
+		unsigned int bugfixes8:1;
+	} reg;
+
+	unsigned int raw;
+};
+
+/*******************************************************************************
+** Register GCMinorFeatures3
+*/
+
+/* Shows which features are enabled in this chip. This register has no set    **
+** reset value, it varies with the implementation.                            */
+
+#define GC_FEATURES3_Address                                             0x00088
+#define GC_FEATURES3_MSB                                                      15
+#define GC_FEATURES3_LSB                                                       0
+#define GC_FEATURES3_BLK                                                       0
+#define GC_FEATURES3_Count                                                     1
+#define GC_FEATURES3_FieldMask                                        0x003FFFFF
+#define GC_FEATURES3_ReadMask                                         0x003FFFFF
+#define GC_FEATURES3_WriteMask                                        0x00000000
+#define GC_FEATURES3_ResetValue                                       0x00000000
+
+#define GC_FEATURES3_DE_ROTATION_STALL_FIX                                 0 : 0
+#define GC_FEATURES3_DE_ROTATION_STALL_FIX_End                                 0
+#define GC_FEATURES3_DE_ROTATION_STALL_FIX_Start                               0
+#define GC_FEATURES3_DE_ROTATION_STALL_FIX_Type                              U01
+#define   GC_FEATURES3_DE_ROTATION_STALL_FIX_NONE                            0x0
+#define   GC_FEATURES3_DE_ROTATION_STALL_FIX_AVAILABLE                       0x1
+
+#define GC_FEATURES3_OCL_ONLY                                              1 : 1
+#define GC_FEATURES3_OCL_ONLY_End                                              1
+#define GC_FEATURES3_OCL_ONLY_Start                                            1
+#define GC_FEATURES3_OCL_ONLY_Type                                           U01
+#define   GC_FEATURES3_OCL_ONLY_NONE                                         0x0
+#define   GC_FEATURES3_OCL_ONLY_AVAILABLE                                    0x1
+
+#define GC_FEATURES3_NEW_FEATURES0                                         2 : 2
+#define GC_FEATURES3_NEW_FEATURES0_End                                         2
+#define GC_FEATURES3_NEW_FEATURES0_Start                                       2
+#define GC_FEATURES3_NEW_FEATURES0_Type                                      U01
+#define   GC_FEATURES3_NEW_FEATURES0_NONE                                    0x0
+#define   GC_FEATURES3_NEW_FEATURES0_AVAILABLE                               0x1
+
+#define GC_FEATURES3_INSTRUCTION_CACHE                                     3 : 3
+#define GC_FEATURES3_INSTRUCTION_CACHE_End                                     3
+#define GC_FEATURES3_INSTRUCTION_CACHE_Start                                   3
+#define GC_FEATURES3_INSTRUCTION_CACHE_Type                                  U01
+#define   GC_FEATURES3_INSTRUCTION_CACHE_NONE                                0x0
+#define   GC_FEATURES3_INSTRUCTION_CACHE_AVAILABLE                           0x1
+
+#define GC_FEATURES3_GEOMETRY_SHADER                                       4 : 4
+#define GC_FEATURES3_GEOMETRY_SHADER_End                                       4
+#define GC_FEATURES3_GEOMETRY_SHADER_Start                                     4
+#define GC_FEATURES3_GEOMETRY_SHADER_Type                                    U01
+#define   GC_FEATURES3_GEOMETRY_SHADER_NONE                                  0x0
+#define   GC_FEATURES3_GEOMETRY_SHADER_AVAILABLE                             0x1
+
+#define GC_FEATURES3_TEX_COMPRESSION_SUPERTILED                            5 : 5
+#define GC_FEATURES3_TEX_COMPRESSION_SUPERTILED_End                            5
+#define GC_FEATURES3_TEX_COMPRESSION_SUPERTILED_Start                          5
+#define GC_FEATURES3_TEX_COMPRESSION_SUPERTILED_Type                         U01
+#define   GC_FEATURES3_TEX_COMPRESSION_SUPERTILED_NONE                       0x0
+#define   GC_FEATURES3_TEX_COMPRESSION_SUPERTILED_AVAILABLE                  0x1
+
+#define GC_FEATURES3_GENERICS                                              6 : 6
+#define GC_FEATURES3_GENERICS_End                                              6
+#define GC_FEATURES3_GENERICS_Start                                            6
+#define GC_FEATURES3_GENERICS_Type                                           U01
+#define   GC_FEATURES3_GENERICS_NONE                                         0x0
+#define   GC_FEATURES3_GENERICS_AVAILABLE                                    0x1
+
+#define GC_FEATURES3_BUG_FIXES9                                            7 : 7
+#define GC_FEATURES3_BUG_FIXES9_End                                            7
+#define GC_FEATURES3_BUG_FIXES9_Start                                          7
+#define GC_FEATURES3_BUG_FIXES9_Type                                         U01
+#define   GC_FEATURES3_BUG_FIXES9_NONE                                       0x0
+#define   GC_FEATURES3_BUG_FIXES9_AVAILABLE                                  0x1
+
+#define GC_FEATURES3_FAST_MSAA                                             8 : 8
+#define GC_FEATURES3_FAST_MSAA_End                                             8
+#define GC_FEATURES3_FAST_MSAA_Start                                           8
+#define GC_FEATURES3_FAST_MSAA_Type                                          U01
+#define   GC_FEATURES3_FAST_MSAA_NONE                                        0x0
+#define   GC_FEATURES3_FAST_MSAA_AVAILABLE                                   0x1
+
+#define GC_FEATURES3_WCLIP                                                 9 : 9
+#define GC_FEATURES3_WCLIP_End                                                 9
+#define GC_FEATURES3_WCLIP_Start                                               9
+#define GC_FEATURES3_WCLIP_Type                                              U01
+#define   GC_FEATURES3_WCLIP_NONE                                            0x0
+#define   GC_FEATURES3_WCLIP_AVAILABLE                                       0x1
+
+#define GC_FEATURES3_BUG_FIXES10                                         10 : 10
+#define GC_FEATURES3_BUG_FIXES10_End                                          10
+#define GC_FEATURES3_BUG_FIXES10_Start                                        10
+#define GC_FEATURES3_BUG_FIXES10_Type                                        U01
+#define   GC_FEATURES3_BUG_FIXES10_NONE                                      0x0
+#define   GC_FEATURES3_BUG_FIXES10_AVAILABLE                                 0x1
+
+#define GC_FEATURES3_UNIFIED_SAMPLERS                                    11 : 11
+#define GC_FEATURES3_UNIFIED_SAMPLERS_End                                     11
+#define GC_FEATURES3_UNIFIED_SAMPLERS_Start                                   11
+#define GC_FEATURES3_UNIFIED_SAMPLERS_Type                                   U01
+#define   GC_FEATURES3_UNIFIED_SAMPLERS_NONE                                 0x0
+#define   GC_FEATURES3_UNIFIED_SAMPLERS_AVAILABLE                            0x1
+
+#define GC_FEATURES3_BUG_FIXES11                                         12 : 12
+#define GC_FEATURES3_BUG_FIXES11_End                                          12
+#define GC_FEATURES3_BUG_FIXES11_Start                                        12
+#define GC_FEATURES3_BUG_FIXES11_Type                                        U01
+#define   GC_FEATURES3_BUG_FIXES11_NONE                                      0x0
+#define   GC_FEATURES3_BUG_FIXES11_AVAILABLE                                 0x1
+
+#define GC_FEATURES3_PERFORMANCE_COUNTERS                                13 : 13
+#define GC_FEATURES3_PERFORMANCE_COUNTERS_End                                 13
+#define GC_FEATURES3_PERFORMANCE_COUNTERS_Start                               13
+#define GC_FEATURES3_PERFORMANCE_COUNTERS_Type                               U01
+#define   GC_FEATURES3_PERFORMANCE_COUNTERS_NONE                             0x0
+#define   GC_FEATURES3_PERFORMANCE_COUNTERS_AVAILABLE                        0x1
+
+/* High precision transcendentals are available. */
+#define GC_FEATURES3_EXTRA_SHADER_INSTRUCTIONS2                          14 : 14
+#define GC_FEATURES3_EXTRA_SHADER_INSTRUCTIONS2_End                           14
+#define GC_FEATURES3_EXTRA_SHADER_INSTRUCTIONS2_Start                         14
+#define GC_FEATURES3_EXTRA_SHADER_INSTRUCTIONS2_Type                         U01
+#define   GC_FEATURES3_EXTRA_SHADER_INSTRUCTIONS2_NONE                       0x0
+#define   GC_FEATURES3_EXTRA_SHADER_INSTRUCTIONS2_AVAILABLE                  0x1
+
+#define GC_FEATURES3_BUG_FIXES12                                         15 : 15
+#define GC_FEATURES3_BUG_FIXES12_End                                          15
+#define GC_FEATURES3_BUG_FIXES12_Start                                        15
+#define GC_FEATURES3_BUG_FIXES12_Type                                        U01
+#define   GC_FEATURES3_BUG_FIXES12_NONE                                      0x0
+#define   GC_FEATURES3_BUG_FIXES12_AVAILABLE                                 0x1
+
+#define GC_FEATURES3_BUG_FIXES13                                         16 : 16
+#define GC_FEATURES3_BUG_FIXES13_End                                          16
+#define GC_FEATURES3_BUG_FIXES13_Start                                        16
+#define GC_FEATURES3_BUG_FIXES13_Type                                        U01
+#define   GC_FEATURES3_BUG_FIXES13_NONE                                      0x0
+#define   GC_FEATURES3_BUG_FIXES13_AVAILABLE                                 0x1
+
+#define GC_FEATURES3_DE_ENHANCEMENTS1                                    17 : 17
+#define GC_FEATURES3_DE_ENHANCEMENTS1_End                                     17
+#define GC_FEATURES3_DE_ENHANCEMENTS1_Start                                   17
+#define GC_FEATURES3_DE_ENHANCEMENTS1_Type                                   U01
+#define   GC_FEATURES3_DE_ENHANCEMENTS1_NONE                                 0x0
+#define   GC_FEATURES3_DE_ENHANCEMENTS1_AVAILABLE                            0x1
+
+#define GC_FEATURES3_ACE                                                 18 : 18
+#define GC_FEATURES3_ACE_End                                                  18
+#define GC_FEATURES3_ACE_Start                                                18
+#define GC_FEATURES3_ACE_Type                                                U01
+#define   GC_FEATURES3_ACE_NONE                                              0x0
+#define   GC_FEATURES3_ACE_AVAILABLE                                         0x1
+
+#define GC_FEATURES3_TX_ENHANCEMENTS1                                    19 : 19
+#define GC_FEATURES3_TX_ENHANCEMENTS1_End                                     19
+#define GC_FEATURES3_TX_ENHANCEMENTS1_Start                                   19
+#define GC_FEATURES3_TX_ENHANCEMENTS1_Type                                   U01
+#define   GC_FEATURES3_TX_ENHANCEMENTS1_NONE                                 0x0
+#define   GC_FEATURES3_TX_ENHANCEMENTS1_AVAILABLE                            0x1
+
+#define GC_FEATURES3_SH_ENHANCEMENTS1                                    20 : 20
+#define GC_FEATURES3_SH_ENHANCEMENTS1_End                                     20
+#define GC_FEATURES3_SH_ENHANCEMENTS1_Start                                   20
+#define GC_FEATURES3_SH_ENHANCEMENTS1_Type                                   U01
+#define   GC_FEATURES3_SH_ENHANCEMENTS1_NONE                                 0x0
+#define   GC_FEATURES3_SH_ENHANCEMENTS1_AVAILABLE                            0x1
+
+#define GC_FEATURES3_SH_ENHANCEMENTS2                                    21 : 21
+#define GC_FEATURES3_SH_ENHANCEMENTS2_End                                     21
+#define GC_FEATURES3_SH_ENHANCEMENTS2_Start                                   21
+#define GC_FEATURES3_SH_ENHANCEMENTS2_Type                                   U01
+#define   GC_FEATURES3_SH_ENHANCEMENTS2_NONE                                 0x0
+#define   GC_FEATURES3_SH_ENHANCEMENTS2_AVAILABLE                            0x1
+
+union gcfeatures3 {
+	struct {
+		/* GC_FEATURES3_Address:DE_ROTATION_STALL_FIX */
+		unsigned int rotationfix:1;
+
+		/* GC_FEATURES3_Address:OCL_ONLY */
+		unsigned int ocl:1;
+
+		/* GC_FEATURES3_Address:NEW_FEATURES0 */
+		unsigned int newfeatures0:1;
+
+		/* GC_FEATURES3_Address:INSTRUCTION_CACHE */
+		unsigned int icache:1;
+
+		/* GC_FEATURES3_Address:GEOMETRY_SHADER */
+		unsigned int gs:1;
+
+		/* GC_FEATURES3_Address:TEX_COMPRESSION_SUPERTILED */
+		unsigned int supertiledtxcompression:1;
+
+		/* GC_FEATURES3_Address:GENERICS */
+		unsigned int generics:1;
+
+		/* GC_FEATURES3_Address:BUG_FIXES9 */
+		unsigned int bugfixes9:1;
+
+		/* GC_FEATURES3_Address:FAST_MSAA */
+		unsigned int fastmsaa:1;
+
+		/* GC_FEATURES3_Address:WCLIP */
+		unsigned int wclip:1;
+
+		/* GC_FEATURES3_Address:BUG_FIXES10 */
+		unsigned int bugfixes10:1;
+
+		/* GC_FEATURES3_Address:UNIFIED_SAMPLERS */
+		unsigned int unifiedsamplers:1;
+
+		/* GC_FEATURES3_Address:BUG_FIXES11 */
+		unsigned int bugfixes11:1;
+
+		/* GC_FEATURES3_Address:PERFORMANCE_COUNTERS */
+		unsigned int perfcounters:1;
+
+		/* GC_FEATURES3_Address:EXTRA_SHADER_INSTRUCTIONS2 */
+		unsigned int shaderinst2:1;
+
+		/* GC_FEATURES3_Address:BUG_FIXES12 */
+		unsigned int bugfixes12:1;
+
+		/* GC_FEATURES3_Address:BUG_FIXES13 */
+		unsigned int bugfixes13:1;
+
+		/* GC_FEATURES3_Address:DE_ENHANCEMENTS1 */
+		unsigned int deenhancements1:1;
+
+		/* GC_FEATURES3_Address:ACE */
+		unsigned int ace:1;
+
+		/* GC_FEATURES3_Address:TX_ENHANCEMENTS1 */
+		unsigned int txenhancements1:1;
+
+		/* GC_FEATURES3_Address:SH_ENHANCEMENTS1 */
+		unsigned int shenhancements1:1;
+
+		/* GC_FEATURES3_Address:SH_ENHANCEMENTS2 */
+		unsigned int shenhancements2:1;
+
+		/* GC_FEATURES3_Address:reserved */
+		unsigned int _reserved_22_31:10;
+	} reg;
+
+	unsigned int raw;
+};
+
+/*******************************************************************************
+** Register GCResetMemCounters
+*/
+
+/* Writing 1 will reset the counters and stop counting. Write 0 to start
+** counting again.  This register is write only so it has no reset value.
+*/
+
+#define GC_RESET_MEM_COUNTERS_Address                                    0x0003C
+#define GC_RESET_MEM_COUNTERS_MSB                                             15
+#define GC_RESET_MEM_COUNTERS_LSB                                              0
+#define GC_RESET_MEM_COUNTERS_BLK                                              0
+#define GC_RESET_MEM_COUNTERS_Count                                            1
+#define GC_RESET_MEM_COUNTERS_FieldMask                               0x00000001
+#define GC_RESET_MEM_COUNTERS_ReadMask                                0x00000000
+#define GC_RESET_MEM_COUNTERS_WriteMask                               0x00000001
+#define GC_RESET_MEM_COUNTERS_ResetValue                              0x00000000
+
+#define GC_RESET_MEM_COUNTERS_RESET                                        0 : 0
+#define GC_RESET_MEM_COUNTERS_RESET_End                                        0
+#define GC_RESET_MEM_COUNTERS_RESET_Start                                      0
+#define GC_RESET_MEM_COUNTERS_RESET_Type                                     U01
+
+/*******************************************************************************
+** Register gcTotalReads
+*/
+
+/* Total reads in terms of 64bits. */
+
+#define GC_TOTAL_READS_Address                                           0x00040
+#define GC_TOTAL_READS_MSB                                                    15
+#define GC_TOTAL_READS_LSB                                                     0
+#define GC_TOTAL_READS_BLK                                                     0
+#define GC_TOTAL_READS_Count                                                   1
+#define GC_TOTAL_READS_FieldMask                                      0xFFFFFFFF
+#define GC_TOTAL_READS_ReadMask                                       0xFFFFFFFF
+#define GC_TOTAL_READS_WriteMask                                      0x00000000
+#define GC_TOTAL_READS_ResetValue                                     0x00000000
+
+#define GC_TOTAL_READS_COUNT                                              31 : 0
+#define GC_TOTAL_READS_COUNT_End                                              31
+#define GC_TOTAL_READS_COUNT_Start                                             0
+#define GC_TOTAL_READS_COUNT_Type                                            U32
+
+/*******************************************************************************
+** Register gcTotalWrites
+*/
+
+/* Total writes in terms of 64bits. */
+
+#define GC_TOTAL_WRITES_Address                                          0x00044
+#define GC_TOTAL_WRITES_MSB                                                   15
+#define GC_TOTAL_WRITES_LSB                                                    0
+#define GC_TOTAL_WRITES_BLK                                                    0
+#define GC_TOTAL_WRITES_Count                                                  1
+#define GC_TOTAL_WRITES_FieldMask                                     0xFFFFFFFF
+#define GC_TOTAL_WRITES_ReadMask                                      0xFFFFFFFF
+#define GC_TOTAL_WRITES_WriteMask                                     0x00000000
+#define GC_TOTAL_WRITES_ResetValue                                    0x00000000
+
+#define GC_TOTAL_WRITES_COUNT                                             31 : 0
+#define GC_TOTAL_WRITES_COUNT_End                                             31
+#define GC_TOTAL_WRITES_COUNT_Start                                            0
+#define GC_TOTAL_WRITES_COUNT_Type                                           U32
+
+/*******************************************************************************
+** Register gcTotalWriteBursts
+*/
+
+/* Total write Data Count in terms of 64bits value. */
+
+#define GC_TOTAL_WRITE_BURSTS_Address                                    0x0004C
+#define GC_TOTAL_WRITE_BURSTS_MSB                                             15
+#define GC_TOTAL_WRITE_BURSTS_LSB                                              0
+#define GC_TOTAL_WRITE_BURSTS_BLK                                              0
+#define GC_TOTAL_WRITE_BURSTS_Count                                            1
+#define GC_TOTAL_WRITE_BURSTS_FieldMask                               0xFFFFFFFF
+#define GC_TOTAL_WRITE_BURSTS_ReadMask                                0xFFFFFFFF
+#define GC_TOTAL_WRITE_BURSTS_WriteMask                               0x00000000
+#define GC_TOTAL_WRITE_BURSTS_ResetValue                              0x00000000
+
+#define GC_TOTAL_WRITE_BURSTS_COUNT                                       31 : 0
+#define GC_TOTAL_WRITE_BURSTS_COUNT_End                                       31
+#define GC_TOTAL_WRITE_BURSTS_COUNT_Start                                      0
+#define GC_TOTAL_WRITE_BURSTS_COUNT_Type                                     U32
+
+/*******************************************************************************
+** Register gcTotalWriteReqs
+*/
+
+/* Total write Request Count. */
+
+#define GC_TOTAL_WRITE_REQS_Address                                      0x00050
+#define GC_TOTAL_WRITE_REQS_MSB                                               15
+#define GC_TOTAL_WRITE_REQS_LSB                                                0
+#define GC_TOTAL_WRITE_REQS_BLK                                                0
+#define GC_TOTAL_WRITE_REQS_Count                                              1
+#define GC_TOTAL_WRITE_REQS_FieldMask                                 0xFFFFFFFF
+#define GC_TOTAL_WRITE_REQS_ReadMask                                  0xFFFFFFFF
+#define GC_TOTAL_WRITE_REQS_WriteMask                                 0x00000000
+#define GC_TOTAL_WRITE_REQS_ResetValue                                0x00000000
+
+#define GC_TOTAL_WRITE_REQS_COUNT                                         31 : 0
+#define GC_TOTAL_WRITE_REQS_COUNT_End                                         31
+#define GC_TOTAL_WRITE_REQS_COUNT_Start                                        0
+#define GC_TOTAL_WRITE_REQS_COUNT_Type                                       U32
+
+/*******************************************************************************
+** Register gcTotalReadBursts
+*/
+
+/* Total Read Data Count in terms of 64bits. */
+
+#define GC_TOTAL_READ_BURSTS_Address                                     0x00058
+#define GC_TOTAL_READ_BURSTS_MSB                                              15
+#define GC_TOTAL_READ_BURSTS_LSB                                               0
+#define GC_TOTAL_READ_BURSTS_BLK                                               0
+#define GC_TOTAL_READ_BURSTS_Count                                             1
+#define GC_TOTAL_READ_BURSTS_FieldMask                                0xFFFFFFFF
+#define GC_TOTAL_READ_BURSTS_ReadMask                                 0xFFFFFFFF
+#define GC_TOTAL_READ_BURSTS_WriteMask                                0x00000000
+#define GC_TOTAL_READ_BURSTS_ResetValue                               0x00000000
+
+#define GC_TOTAL_READ_BURSTS_COUNT                                        31 : 0
+#define GC_TOTAL_READ_BURSTS_COUNT_End                                        31
+#define GC_TOTAL_READ_BURSTS_COUNT_Start                                       0
+#define GC_TOTAL_READ_BURSTS_COUNT_Type                                      U32
+
+/*******************************************************************************
+** Register gcTotalReadReqs
+*/
+
+/* Total Read Request Count. */
+
+#define GC_TOTAL_READ_REQS_Address                                       0x0005C
+#define GC_TOTAL_READ_REQS_MSB                                                15
+#define GC_TOTAL_READ_REQS_LSB                                                 0
+#define GC_TOTAL_READ_REQS_BLK                                                 0
+#define GC_TOTAL_READ_REQS_Count                                               1
+#define GC_TOTAL_READ_REQS_FieldMask                                  0xFFFFFFFF
+#define GC_TOTAL_READ_REQS_ReadMask                                   0xFFFFFFFF
+#define GC_TOTAL_READ_REQS_WriteMask                                  0x00000000
+#define GC_TOTAL_READ_REQS_ResetValue                                 0x00000000
+
+#define GC_TOTAL_READ_REQS_COUNT                                          31 : 0
+#define GC_TOTAL_READ_REQS_COUNT_End                                          31
+#define GC_TOTAL_READ_REQS_COUNT_Start                                         0
+#define GC_TOTAL_READ_REQS_COUNT_Type                                        U32
+
+/*******************************************************************************
+** Register gcTotalReadLasts
+*/
+
+/* Total RLAST Count. This is used to match with GCTotalReadReqs. */
+
+#define GC_TOTAL_READ_LASTS_Address                                      0x00060
+#define GC_TOTAL_READ_LASTS_MSB                                               15
+#define GC_TOTAL_READ_LASTS_LSB                                                0
+#define GC_TOTAL_READ_LASTS_BLK                                                0
+#define GC_TOTAL_READ_LASTS_Count                                              1
+#define GC_TOTAL_READ_LASTS_FieldMask                                 0xFFFFFFFF
+#define GC_TOTAL_READ_LASTS_ReadMask                                  0xFFFFFFFF
+#define GC_TOTAL_READ_LASTS_WriteMask                                 0x00000000
+#define GC_TOTAL_READ_LASTS_ResetValue                                0x00000000
+
+#define GC_TOTAL_READ_LASTS_COUNT                                         31 : 0
+#define GC_TOTAL_READ_LASTS_COUNT_End                                         31
+#define GC_TOTAL_READ_LASTS_COUNT_Start                                        0
+#define GC_TOTAL_READ_LASTS_COUNT_Type                                       U32
+
+/*******************************************************************************
+** Register gcGpOut0
+*/
+
+/* General Purpose output register0. R/W but not connected to anywhere. */
+
+#define GC_GP_OUT0_Address                                               0x00064
+#define GC_GP_OUT0_MSB                                                        15
+#define GC_GP_OUT0_LSB                                                         0
+#define GC_GP_OUT0_BLK                                                         0
+#define GC_GP_OUT0_Count                                                       1
+#define GC_GP_OUT0_FieldMask                                          0xFFFFFFFF
+#define GC_GP_OUT0_ReadMask                                           0xFFFFFFFF
+#define GC_GP_OUT0_WriteMask                                          0xFFFFFFFF
+#define GC_GP_OUT0_ResetValue                                         0x00000000
+
+#define GC_GP_OUT0_COUNT                                                  31 : 0
+#define GC_GP_OUT0_COUNT_End                                                  31
+#define GC_GP_OUT0_COUNT_Start                                                 0
+#define GC_GP_OUT0_COUNT_Type                                                U32
+
+/*******************************************************************************
+** Register gcGpOut1
+*/
+
+/* General Purpose output register1. R/W but not connected to anywhere. */
+
+#define GC_GP_OUT1_Address                                               0x00068
+#define GC_GP_OUT1_MSB                                                        15
+#define GC_GP_OUT1_LSB                                                         0
+#define GC_GP_OUT1_BLK                                                         0
+#define GC_GP_OUT1_Count                                                       1
+#define GC_GP_OUT1_FieldMask                                          0xFFFFFFFF
+#define GC_GP_OUT1_ReadMask                                           0xFFFFFFFF
+#define GC_GP_OUT1_WriteMask                                          0xFFFFFFFF
+#define GC_GP_OUT1_ResetValue                                         0x00000000
+
+#define GC_GP_OUT1_COUNT                                                  31 : 0
+#define GC_GP_OUT1_COUNT_End                                                  31
+#define GC_GP_OUT1_COUNT_Start                                                 0
+#define GC_GP_OUT1_COUNT_Type                                                U32
+
+/*******************************************************************************
+** Register gcGpOut2
+*/
+
+/* General Purpose output register2. R/W but not connected to anywhere. */
+
+#define GC_GP_OUT2_Address                                               0x0006C
+#define GC_GP_OUT2_MSB                                                        15
+#define GC_GP_OUT2_LSB                                                         0
+#define GC_GP_OUT2_BLK                                                         0
+#define GC_GP_OUT2_Count                                                       1
+#define GC_GP_OUT2_FieldMask                                          0xFFFFFFFF
+#define GC_GP_OUT2_ReadMask                                           0xFFFFFFFF
+#define GC_GP_OUT2_WriteMask                                          0xFFFFFFFF
+#define GC_GP_OUT2_ResetValue                                         0x00000000
+
+#define GC_GP_OUT2_COUNT                                                  31 : 0
+#define GC_GP_OUT2_COUNT_End                                                  31
+#define GC_GP_OUT2_COUNT_Start                                                 0
+#define GC_GP_OUT2_COUNT_Type                                                U32
+
+/*******************************************************************************
+** Register gcAxiControl
+*/
+
+/* Special Handling on AXI Bus */
+
+#define GC_AXI_CONTROL_Address                                           0x00070
+#define GC_AXI_CONTROL_MSB                                                    15
+#define GC_AXI_CONTROL_LSB                                                     0
+#define GC_AXI_CONTROL_BLK                                                     0
+#define GC_AXI_CONTROL_Count                                                   1
+#define GC_AXI_CONTROL_FieldMask                                      0x00000001
+#define GC_AXI_CONTROL_ReadMask                                       0x00000001
+#define GC_AXI_CONTROL_WriteMask                                      0x00000001
+#define GC_AXI_CONTROL_ResetValue                                     0x00000000
+
+#define GC_AXI_CONTROL_WR_FULL_BURST_MODE                                  0 : 0
+#define GC_AXI_CONTROL_WR_FULL_BURST_MODE_End                                  0
+#define GC_AXI_CONTROL_WR_FULL_BURST_MODE_Start                                0
+#define GC_AXI_CONTROL_WR_FULL_BURST_MODE_Type                               U01
+#define   GC_AXI_CONTROL_WR_FULL_BURST_MODE_NO_BURST_RESET_VALUE             0x0
+#define   GC_AXI_CONTROL_WR_FULL_BURST_MODE_BURST_RESET_VALUE                0x1
+
+/*******************************************************************************
+** Register gcTotalCycles
+*/
+
+/* Total cycles. This register is a free running counter.  It can be reset by
+** writing 0 to it.
+*/
+
+#define GC_TOTAL_CYCLES_Address                                          0x00078
+#define GC_TOTAL_CYCLES_MSB                                                   15
+#define GC_TOTAL_CYCLES_LSB                                                    0
+#define GC_TOTAL_CYCLES_BLK                                                    0
+#define GC_TOTAL_CYCLES_Count                                                  1
+#define GC_TOTAL_CYCLES_FieldMask                                     0xFFFFFFFF
+#define GC_TOTAL_CYCLES_ReadMask                                      0xFFFFFFFF
+#define GC_TOTAL_CYCLES_WriteMask                                     0xFFFFFFFF
+#define GC_TOTAL_CYCLES_ResetValue                                    0x00000000
+
+#define GC_TOTAL_CYCLES_CYCLES                                            31 : 0
+#define GC_TOTAL_CYCLES_CYCLES_End                                            31
+#define GC_TOTAL_CYCLES_CYCLES_Start                                           0
+#define GC_TOTAL_CYCLES_CYCLES_Type                                          U32
+
+/*******************************************************************************
+** Register gcTotalIdleCycles
+*/
+
+/* Total cycles where the GPU is idle. It is reset when  gcTotalCycles register
+** is written to. It looks at all the blocks but FE when determining the IP is
+** idle.
+*/
+
+#define GC_TOTAL_IDLE_CYCLES_Address                                     0x0007C
+#define GC_TOTAL_IDLE_CYCLES_MSB                                              15
+#define GC_TOTAL_IDLE_CYCLES_LSB                                               0
+#define GC_TOTAL_IDLE_CYCLES_BLK                                               0
+#define GC_TOTAL_IDLE_CYCLES_Count                                             1
+#define GC_TOTAL_IDLE_CYCLES_FieldMask                                0xFFFFFFFF
+#define GC_TOTAL_IDLE_CYCLES_ReadMask                                 0xFFFFFFFF
+#define GC_TOTAL_IDLE_CYCLES_WriteMask                                0xFFFFFFFF
+#define GC_TOTAL_IDLE_CYCLES_ResetValue                               0x00000000
+
+#define GC_TOTAL_IDLE_CYCLES_CYCLES                                       31 : 0
+#define GC_TOTAL_IDLE_CYCLES_CYCLES_End                                       31
+#define GC_TOTAL_IDLE_CYCLES_CYCLES_Start                                      0
+#define GC_TOTAL_IDLE_CYCLES_CYCLES_Type                                     U32
+
+/*******************************************************************************
+** Command opcodes.
+*/
+
+#define GCREG_COMMAND_OPCODE_LOAD_STATE                                     0x01
+#define GCREG_COMMAND_OPCODE_END                                            0x02
+#define GCREG_COMMAND_OPCODE_NOP                                            0x03
+#define GCREG_COMMAND_OPCODE_STARTDE                                        0x04
+#define GCREG_COMMAND_OPCODE_WAIT                                           0x07
+#define GCREG_COMMAND_OPCODE_LINK                                           0x08
+#define GCREG_COMMAND_OPCODE_STALL                                          0x09
+#define GCREG_COMMAND_OPCODE_CALL                                           0x0A
+#define GCREG_COMMAND_OPCODE_RETURN                                         0x0B
+
+/*******************************************************************************
+** Command gcregCommandLoadState
+*/
+
+/* When enabled, convert 16.16 fixed point into 32-bit floating point. */
+#define GCREG_COMMAND_LOAD_STATE_FLOAT                                   26 : 26
+#define GCREG_COMMAND_LOAD_STATE_FLOAT_End                                    26
+#define GCREG_COMMAND_LOAD_STATE_FLOAT_Start                                  26
+#define GCREG_COMMAND_LOAD_STATE_FLOAT_Type                                  U01
+#define   GCREG_COMMAND_LOAD_STATE_FLOAT_NORMAL                              0x0
+#define   GCREG_COMMAND_LOAD_STATE_FLOAT_FIXED16_DOT16                       0x1
+
+/* Number of states. 0 = 1024. */
+#define GCREG_COMMAND_LOAD_STATE_COUNT                                   25 : 16
+#define GCREG_COMMAND_LOAD_STATE_COUNT_End                                    25
+#define GCREG_COMMAND_LOAD_STATE_COUNT_Start                                  16
+#define GCREG_COMMAND_LOAD_STATE_COUNT_Type                                  U10
+
+/* Starting state address. */
+#define GCREG_COMMAND_LOAD_STATE_ADDRESS                                  15 : 0
+#define GCREG_COMMAND_LOAD_STATE_ADDRESS_End                                  15
+#define GCREG_COMMAND_LOAD_STATE_ADDRESS_Start                                 0
+#define GCREG_COMMAND_LOAD_STATE_ADDRESS_Type                                U16
+
+#define GCREG_COMMAND_LOAD_STATE_OPCODE                                  31 : 27
+#define GCREG_COMMAND_LOAD_STATE_OPCODE_End                                   31
+#define GCREG_COMMAND_LOAD_STATE_OPCODE_Start                                 27
+#define GCREG_COMMAND_LOAD_STATE_OPCODE_Type                                 U05
+
+struct gccmdldstate {
+	/* gcregCommandLoadState:GCREG_COMMAND_LOAD_STATE_ADDRESS */
+	unsigned int address:16;
+
+	/* gcregCommandLoadState:GCREG_COMMAND_LOAD_STATE_COUNT */
+	unsigned int count:10;
+
+	/* gcregCommandLoadState:GCREG_COMMAND_LOAD_STATE_FLOAT */
+	unsigned int fixed:1;
+
+	/* gcregCommandLoadState:GCREG_COMMAND_LOAD_STATE_OPCODE */
+	unsigned int opcode:5;
+};
+
+#define GCLDSTATE(Address, Count) \
+{ \
+	/* gcregCommandLoadState:GCREG_COMMAND_LOAD_STATE_ADDRESS */ \
+	Address, \
+	\
+	/* gcregCommandLoadState:GCREG_COMMAND_LOAD_STATE_COUNT */ \
+	Count, \
+	\
+	/* gcregCommandLoadState:GCREG_COMMAND_LOAD_STATE_FLOAT */ \
+	GCREG_COMMAND_LOAD_STATE_FLOAT_NORMAL, \
+	\
+	/* gcregCommandLoadState:GCREG_COMMAND_LOAD_STATE_OPCODE */ \
+	GCREG_COMMAND_OPCODE_LOAD_STATE \
+}
+
+/*******************************************************************************
+** Command gcregCommandEnd
+*/
+
+/* Send event when END is completed. */
+#define GCREG_COMMAND_END_EVENT                                            8 : 8
+#define GCREG_COMMAND_END_EVENT_End                                            8
+#define GCREG_COMMAND_END_EVENT_Start                                          8
+#define GCREG_COMMAND_END_EVENT_Type                                         U01
+#define   GCREG_COMMAND_END_EVENT_DISABLE                                    0x0
+#define   GCREG_COMMAND_END_EVENT_ENABLE                                     0x1
+
+/* Event ID to be send. */
+#define GCREG_COMMAND_END_EVENT_ID                                         4 : 0
+#define GCREG_COMMAND_END_EVENT_ID_End                                         4
+#define GCREG_COMMAND_END_EVENT_ID_Start                                       0
+#define GCREG_COMMAND_END_EVENT_ID_Type                                      U05
+
+#define GCREG_COMMAND_END_OPCODE                                         31 : 27
+#define GCREG_COMMAND_END_OPCODE_End                                          31
+#define GCREG_COMMAND_END_OPCODE_Start                                        27
+#define GCREG_COMMAND_END_OPCODE_Type                                        U05
+
+struct gcfldend {
+	/* gcregCommandEnd:GCREG_COMMAND_END_EVENT_ID */
+	unsigned int signalid:5;
+
+	/* gcregCommandEnd:reserved */
+	unsigned int _reserved_5_7:3;
+
+	/* gcregCommandEnd:GCREG_COMMAND_END_EVENT_ENABLE */
+	unsigned int signal:1;
+
+	/* gcregCommandEnd:reserved */
+	unsigned int _reserved_9_26:18;
+
+	/* gcregCommandEnd:GCREG_COMMAND_END_OPCODE */
+	unsigned int opcode:5;
+};
+
+struct gccmdend {
+	union {
+		struct gcfldend fld;
+		unsigned int raw;
+	}
+	cmd;
+
+	/* Alignment filler. */
+	unsigned int _filler;
+};
+
+static const struct gccmdend gccmdend_const = {
+	/* cmd */
+	{
+		/* fld */
+		{
+			/* gcregCommandEnd:GCREG_COMMAND_END_EVENT_ID */
+			0,
+
+			/* gcregCommandEnd:reserved */
+			0,
+
+			/* gcregCommandEnd:GCREG_COMMAND_END_EVENT */
+			GCREG_COMMAND_END_EVENT_DISABLE,
+
+			/* gcregCommandEnd:reserved */
+			0,
+
+			/* gcregCommandEnd:GCREG_COMMAND_END_OPCODE */
+			GCREG_COMMAND_OPCODE_END
+		}
+	},
+
+	/* Alignment filler. */
+	0
+};
+
+/*******************************************************************************
+** Command gcregCommandNop
+*/
+
+#define GCREG_COMMAND_NOP_OPCODE                                         31 : 27
+#define GCREG_COMMAND_NOP_OPCODE_End                                          31
+#define GCREG_COMMAND_NOP_OPCODE_Start                                        27
+#define GCREG_COMMAND_NOP_OPCODE_Type                                        U05
+
+struct gcfldnop {
+	/* gcregCommandNop:reserved */
+	unsigned int _reserved_0_26:27;
+
+	/* gcregCommandNop:GCREG_COMMAND_NOP_OPCODE */
+	unsigned int opcode:5;
+};
+
+struct gccmdnop {
+	union {
+		struct gcfldnop fld;
+		unsigned int raw;
+	}
+	cmd;
+
+	/* Alignment filler. */
+	unsigned int _filler;
+};
+
+static const struct gccmdnop gccmdnop_const = {
+	/* cmd */
+	{
+		/* fld */
+		{
+			/* gcregCommandNop:reserved */
+			0,
+
+			/* gcregCommandNop:GCREG_COMMAND_NOP_OPCODE */
+			GCREG_COMMAND_OPCODE_NOP
+		}
+	},
+
+	/* Alignment filler. */
+	0
+};
+
+/*******************************************************************************
+** Command gcregCommandStartDE
+*/
+
+/* Offset Command
+** ~~~~~~~~~~~~~~ */
+
+/* Number of 32-bit data words to send.
+** The data follows the rectangles, aligned at 64-bit.
+*/
+#define GCREG_COMMAND_STARTDE_DATA_COUNT                                 26 : 16
+#define GCREG_COMMAND_STARTDE_DATA_COUNT_End                                  26
+#define GCREG_COMMAND_STARTDE_DATA_COUNT_Start                                16
+#define GCREG_COMMAND_STARTDE_DATA_COUNT_Type                                U11
+
+/* Number of rectangles to send.
+** The rectangles follow the command, aligned at 64-bit.
+*/
+#define GCREG_COMMAND_STARTDE_COUNT                                       15 : 8
+#define GCREG_COMMAND_STARTDE_COUNT_End                                       15
+#define GCREG_COMMAND_STARTDE_COUNT_Start                                      8
+#define GCREG_COMMAND_STARTDE_COUNT_Type                                     U08
+
+#define GCREG_COMMAND_STARTDE_OPCODE                                     31 : 27
+#define GCREG_COMMAND_STARTDE_OPCODE_End                                      31
+#define GCREG_COMMAND_STARTDE_OPCODE_Start                                    27
+#define GCREG_COMMAND_STARTDE_OPCODE_Type                                    U05
+
+struct gcfldstartde {
+	/* gcregCommandStartDE:reserved */
+	unsigned int _reserved_0_7:8;
+
+	/* gcregCommandStartDE:GCREG_COMMAND_STARTDE_COUNT */
+	unsigned int rectcount:8;
+
+	/* gcregCommandStartDE:GCREG_COMMAND_STARTDE_DATA_COUNT */
+	unsigned int datacount:11;
+
+	/* gcregCommandStartDE:GCREG_COMMAND_STARTDE_OPCODE */
+	unsigned int opcode:5;
+};
+
+struct gccmdstartde {
+	union {
+		struct gcfldstartde fld;
+		unsigned int raw;
+	} cmd;
+
+	/* Alignment filler. */
+	unsigned int _filler;
+};
+
+static const struct gcfldstartde gcfldstartde = {
+	/* gcregCommandStartDE:reserved */
+	0,
+
+	/* gcregCommandStartDE:GCREG_COMMAND_STARTDE_COUNT */
+	1,
+
+	/* gcregCommandStartDE:GCREG_COMMAND_STARTDE_DATA_COUNT */
+	0,
+
+	/* gcregCommandStartDE:GCREG_COMMAND_STARTDE_OPCODE */
+	GCREG_COMMAND_OPCODE_STARTDE
+};
+
+/* Offset TopLeft
+** ~~~~~~~~~~~~~~ */
+
+#define GCREG_COMMAND_TOP_LEFT_Y                                         31 : 16
+#define GCREG_COMMAND_TOP_LEFT_Y_End                                          31
+#define GCREG_COMMAND_TOP_LEFT_Y_Start                                        16
+#define GCREG_COMMAND_TOP_LEFT_Y_Type                                        U16
+
+#define GCREG_COMMAND_TOP_LEFT_X                                          15 : 0
+#define GCREG_COMMAND_TOP_LEFT_X_End                                          15
+#define GCREG_COMMAND_TOP_LEFT_X_Start                                         0
+#define GCREG_COMMAND_TOP_LEFT_X_Type                                        U16
+
+/* Offset BottomRight
+** ~~~~~~~~~~~~~~~~~~ */
+
+#define GCREG_COMMAND_BOTTOM_RIGHT_Y                                     31 : 16
+#define GCREG_COMMAND_BOTTOM_RIGHT_Y_End                                      31
+#define GCREG_COMMAND_BOTTOM_RIGHT_Y_Start                                    16
+#define GCREG_COMMAND_BOTTOM_RIGHT_Y_Type                                    U16
+
+#define GCREG_COMMAND_BOTTOM_RIGHT_X                                      15 : 0
+#define GCREG_COMMAND_BOTTOM_RIGHT_X_End                                      15
+#define GCREG_COMMAND_BOTTOM_RIGHT_X_Start                                     0
+#define GCREG_COMMAND_BOTTOM_RIGHT_X_Type                                    U16
+
+struct gccmdstartderect {
+	/* GCREG_COMMAND_TOP_LEFT_X */
+	unsigned int left:16;
+
+	/* GCREG_COMMAND_TOP_LEFT_Y */
+	unsigned int top:16;
+
+	/* GCREG_COMMAND_BOTTOM_RIGHT_X */
+	unsigned int right:16;
+
+	/* GCREG_COMMAND_BOTTOM_RIGHT_Y */
+	unsigned int bottom:16;
+};
+
+/*******************************************************************************
+** Command gcregCommandWait
+*/
+
+/* Number of cycles to wait until the next command gets fetched. */
+#define GCREG_COMMAND_WAIT_DELAY                                          15 : 0
+#define GCREG_COMMAND_WAIT_DELAY_End                                          15
+#define GCREG_COMMAND_WAIT_DELAY_Start                                         0
+#define GCREG_COMMAND_WAIT_DELAY_Type                                        U16
+
+#define GCREG_COMMAND_WAIT_OPCODE                                        31 : 27
+#define GCREG_COMMAND_WAIT_OPCODE_End                                         31
+#define GCREG_COMMAND_WAIT_OPCODE_Start                                       27
+#define GCREG_COMMAND_WAIT_OPCODE_Type                                       U05
+
+struct gcfldwait {
+	/* gcregCommandWait:GCREG_COMMAND_WAIT_DELAY */
+	unsigned int delay:16;
+
+	/* gcregCommandWait:reserved */
+	unsigned int _reserved_16_26:11;
+
+	/* gcregCommandWait:GCREG_COMMAND_WAIT_OPCODE */
+	unsigned int opcode:5;
+};
+
+struct gccmdwait {
+	union {
+		struct gcfldwait fld;
+		unsigned int raw;
+	} cmd;
+
+	/* Alignment filler. */
+	unsigned int _filler;
+};
+
+static const struct gcfldwait gcfldwait200 = {
+	/* gcregCommandWait:GCREG_COMMAND_WAIT_DELAY */
+	200,
+
+	/* gcregCommandWait:reserved */
+	0,
+
+	/* gcregCommandWait:GCREG_COMMAND_WAIT_OPCODE */
+	GCREG_COMMAND_OPCODE_WAIT
+};
+
+/*******************************************************************************
+** Command gcregCommandLink
+*/
+
+/* Number of 64-bit words to fetch.  Make sure this number is not too low,
+** nothing else will be fetched.  So, make sure that the last command in the
+** new command buffer is either an END, a LINK, a CALL, or a RETURN.
+*/
+#define GCREG_COMMAND_LINK_PREFETCH                                       15 : 0
+#define GCREG_COMMAND_LINK_PREFETCH_End                                       15
+#define GCREG_COMMAND_LINK_PREFETCH_Start                                      0
+#define GCREG_COMMAND_LINK_PREFETCH_Type                                     U16
+
+#define GCREG_COMMAND_LINK_OPCODE                                        31 : 27
+#define GCREG_COMMAND_LINK_OPCODE_End                                         31
+#define GCREG_COMMAND_LINK_OPCODE_Start                                       27
+#define GCREG_COMMAND_LINK_OPCODE_Type                                       U05
+
+/* Offset Address
+** ~~~~~~~~~~~~~~ */
+#define GCREG_COMMAND_LINK_ADDRESS_Index                                       1
+#define GCREG_COMMAND_LINK_ADDRESS_CmdAddrs                               0x0F0D
+
+#define GCREG_COMMAND_LINK_ADDRESS_ADDRESS                                31 : 0
+#define GCREG_COMMAND_LINK_ADDRESS_ADDRESS_End                                30
+#define GCREG_COMMAND_LINK_ADDRESS_ADDRESS_Start                               0
+#define GCREG_COMMAND_LINK_ADDRESS_ADDRESS_Type                              U31
+
+struct gcfldlink {
+	/* gcregCommandLink:GCREG_COMMAND_LINK_PREFETCH */
+	unsigned int count:16;
+
+	/* gcregCommandLink:reserved */
+	unsigned int _reserved_16_26:11;
+
+	/* gcregCommandLink:GCREG_COMMAND_LINK_OPCODE */
+	unsigned int opcode:5;
+};
+
+struct gccmdlink {
+	union {
+		struct gcfldlink fld;
+		unsigned int raw;
+	} cmd;
+
+	/* gcregCommandLink:GCREG_COMMAND_LINK_ADDRESS_ADDRESS */
+	unsigned int address;
+};
+
+static const struct gcfldlink gcfldlink2 = {
+	/* gcregCommandLink:GCREG_COMMAND_LINK_PREFETCH */
+	2,
+
+	/* gcregCommandLink:reserved */
+	0,
+
+	/* gcregCommandLink:GCREG_COMMAND_LINK_OPCODE */
+	GCREG_COMMAND_OPCODE_LINK
+};
+
+static const struct gcfldlink gcfldlink4 = {
+	/* gcregCommandLink:GCREG_COMMAND_LINK_PREFETCH */
+	4,
+
+	/* gcregCommandLink:reserved */
+	0,
+
+	/* gcregCommandLink:GCREG_COMMAND_LINK_OPCODE */
+	GCREG_COMMAND_OPCODE_LINK
+};
+
+/*******************************************************************************
+** Command gcregCommandStall
+*/
+
+/* Offset Command
+** ~~~~~~~~~~~~~~ */
+#define GCREG_COMMAND_STALL_OPCODE                                       31 : 27
+#define GCREG_COMMAND_STALL_OPCODE_End                                        31
+#define GCREG_COMMAND_STALL_OPCODE_Start                                      27
+#define GCREG_COMMAND_STALL_OPCODE_Type                                      U05
+
+/* Offset Stall
+** ~~~~~~~~~~~~ */
+#define GCREG_COMMAND_STALL_STALL_SOURCE                                   4 : 0
+#define GCREG_COMMAND_STALL_STALL_SOURCE_End                                   4
+#define GCREG_COMMAND_STALL_STALL_SOURCE_Start                                 0
+#define GCREG_COMMAND_STALL_STALL_SOURCE_Type                                U05
+#define   GCREG_COMMAND_STALL_STALL_SOURCE_FRONT_END                        0x01
+#define   GCREG_COMMAND_STALL_STALL_SOURCE_PIXEL_ENGINE                     0x07
+#define   GCREG_COMMAND_STALL_STALL_SOURCE_DRAWING_ENGINE                   0x0B
+
+#define GCREG_COMMAND_STALL_STALL_DESTINATION                             12 : 8
+#define GCREG_COMMAND_STALL_STALL_DESTINATION_End                             12
+#define GCREG_COMMAND_STALL_STALL_DESTINATION_Start                            8
+#define GCREG_COMMAND_STALL_STALL_DESTINATION_Type                           U05
+#define   GCREG_COMMAND_STALL_STALL_DESTINATION_FRONT_END                   0x01
+#define   GCREG_COMMAND_STALL_STALL_DESTINATION_PIXEL_ENGINE                0x07
+#define   GCREG_COMMAND_STALL_STALL_DESTINATION_DRAWING_ENGINE              0x0B
+
+struct gcfldstall {
+	/* gcregCommandStall:reserved */
+	unsigned int _reserved_0_26:27;
+
+	/* gcregCommandStall:GCREG_COMMAND_STALL_OPCODE */
+	unsigned int opcode:5;
+};
+
+struct gcfldstallarg {
+	/* gcregCommandStall:GCREG_COMMAND_STALL_STALL_SOURCE */
+	unsigned int src:5;
+
+	/* gcregCommandStall:reserved */
+	unsigned int _reserved_5_7:3;
+
+	/* gcregCommandStall:GCREG_COMMAND_STALL_STALL_DESTINATION */
+	unsigned int dst:5;
+
+	/* gcregCommandStall:reserved */
+	unsigned int _reserved_13_31:19;
+};
+
+struct gccmdstall {
+	union {
+		struct gcfldstall fld;
+		unsigned int raw;
+	} cmd;
+
+	union {
+		struct gcfldstallarg fld;
+		unsigned int raw;
+	} arg;
+};
+
+static const struct gcfldstall gcfldstall = {
+	/* gcregCommandStall:reserved */
+	0,
+
+	/* gcregCommandStall:GCREG_COMMAND_STALL_OPCODE */
+	GCREG_COMMAND_OPCODE_STALL
+};
+
+static const struct gcfldstallarg gcfldstall_fe_pe = {
+	/* gcregCommandStall:GCREG_COMMAND_STALL_STALL_SOURCE */
+	GCREG_COMMAND_STALL_STALL_SOURCE_FRONT_END,
+
+	/* gcregCommandStall:reserved */
+	0,
+
+	/* gcregCommandStall:GCREG_COMMAND_STALL_STALL_DESTINATION */
+	GCREG_COMMAND_STALL_STALL_DESTINATION_PIXEL_ENGINE,
+
+	/* gcregCommandStall:reserved */
+	0
+};
+
+/*******************************************************************************
+** Command gcregCommandCall
+*/
+
+/* Offset Command
+** ~~~~~~~~~~~~~~ */
+
+/* Number of 64-bit words to fetch.  Make sure this number is not too low,
+** nothing else will be fetched.  So, make sure that the last command in the
+** new command buffer is either an END, a LINK, a CALL, or a RETURN.
+*/
+#define GCREG_COMMAND_CALL_PREFETCH                                       15 : 0
+#define GCREG_COMMAND_CALL_PREFETCH_End                                       15
+#define GCREG_COMMAND_CALL_PREFETCH_Start                                      0
+#define GCREG_COMMAND_CALL_PREFETCH_Type                                     U16
+
+#define GCREG_COMMAND_CALL_OPCODE                                        31 : 27
+#define GCREG_COMMAND_CALL_OPCODE_End                                         31
+#define GCREG_COMMAND_CALL_OPCODE_Start                                       27
+#define GCREG_COMMAND_CALL_OPCODE_Type                                       U05
+
+/* Offset Address
+** ~~~~~~~~~~~~~~ */
+
+#define GCREG_COMMAND_CALL_ADDRESS_ADDRESS                                31 : 0
+#define GCREG_COMMAND_CALL_ADDRESS_ADDRESS_End                                30
+#define GCREG_COMMAND_CALL_ADDRESS_ADDRESS_Start                               0
+#define GCREG_COMMAND_CALL_ADDRESS_ADDRESS_Type                              U31
+
+/* Offset ReturnPrefetch
+** ~~~~~~~~~~~~~~~~~~~~~ */
+
+/* Number of 64-bit words to fetch after a Return has been issued.  Make sure **
+** this number if not too low nothing else will be fetched.  So, make sure    **
+** the last command in this prefetch block is either an END, a LINK, a CALL,  **
+** or a RETURN.                                                               */
+#define GCREG_COMMAND_CALL_RETURN_PREFETCH_PREFETCH                       15 : 0
+#define GCREG_COMMAND_CALL_RETURN_PREFETCH_PREFETCH_End                       15
+#define GCREG_COMMAND_CALL_RETURN_PREFETCH_PREFETCH_Start                      0
+#define GCREG_COMMAND_CALL_RETURN_PREFETCH_PREFETCH_Type                     U16
+
+/* Offset ReturnAddress
+** ~~~~~~~~~~~~~~~~~~~~ */
+
+#define GCREG_COMMAND_CALL_RETURN_ADDRESS_ADDRESS                         31 : 0
+#define GCREG_COMMAND_CALL_RETURN_ADDRESS_ADDRESS_End                         30
+#define GCREG_COMMAND_CALL_RETURN_ADDRESS_ADDRESS_Start                        0
+#define GCREG_COMMAND_CALL_RETURN_ADDRESS_ADDRESS_Type                       U31
+
+struct gccmdcall {
+	/* gcregCommandCall:GCREG_COMMAND_CALL_PREFETCH */
+	unsigned int count:16;
+
+	/* gcregCommandCall:reserved */
+	unsigned int _reserved_16_26:11;
+
+	/* gcregCommandCall:GCREG_COMMAND_CALL_OPCODE */
+	unsigned int opcode:5;
+
+	/* gcregCommandCall:GCREG_COMMAND_CALL_ADDRESS_ADDRESS */
+	unsigned int address;
+
+	/* gcregCommandCall:GCREG_COMMAND_CALL_RETURN_PREFETCH_PREFETCH */
+	unsigned int retcount;
+
+	/* gcregCommandCall:GCREG_COMMAND_CALL_RETURN_ADDRESS_ADDRESS */
+	unsigned int retaddress;
+};
+
+/*******************************************************************************
+** Command gccmdCommandReturn
+*/
+
+#define GCREG_COMMAND_RETURN_OPCODE                                      31 : 27
+#define GCREG_COMMAND_RETURN_OPCODE_End                                       31
+#define GCREG_COMMAND_RETURN_OPCODE_Start                                     27
+#define GCREG_COMMAND_RETURN_OPCODE_Type                                     U05
+
+struct gcfldret {
+	/* gccmdCommandReturn:reserved */
+	unsigned int _reserved_0_26:27;
+
+	/* gccmdCommandReturn:GCREG_COMMAND_RETURN_OPCODE */
+	unsigned int opcode:5;
+};
+
+struct gccmdret {
+	union {
+		struct gcfldret fld;
+		unsigned int raw;
+	}
+	cmd;
+
+	/* Alignment filler. */
+	unsigned int _filler;
+};
+
+static const struct gcfldret gcfldret = {
+	/* gccmdCommandReturn:reserved */
+	0,
+
+	/* gccmdCommandReturn:GCREG_COMMAND_RETURN_OPCODE */
+	GCREG_COMMAND_OPCODE_RETURN
+};
+
+/*******************************************************************************
+** State gcregStall
+*/
+
+#define gcregStallRegAddrs                                                0x0F00
+#define GCREG_STALL_Count                                                      1
+#define GCREG_STALL_ResetValue                                        0x00000000
+
+#define GCREG_STALL_FLIP0                                                30 : 30
+#define GCREG_STALL_FLIP0_End                                                 30
+#define GCREG_STALL_FLIP0_Start                                               30
+#define GCREG_STALL_FLIP0_Type                                               U01
+
+#define GCREG_STALL_FLIP1                                                31 : 31
+#define GCREG_STALL_FLIP1_End                                                 31
+#define GCREG_STALL_FLIP1_Start                                               31
+#define GCREG_STALL_FLIP1_Type                                               U01
+
+#define GCREG_STALL_SOURCE                                                 4 : 0
+#define GCREG_STALL_SOURCE_End                                                 4
+#define GCREG_STALL_SOURCE_Start                                               0
+#define GCREG_STALL_SOURCE_Type                                              U05
+#define   GCREG_STALL_SOURCE_FRONT_END                                      0x01
+#define   GCREG_STALL_SOURCE_PIXEL_ENGINE                                   0x07
+#define   GCREG_STALL_SOURCE_DRAWING_ENGINE                                 0x0B
+
+#define GCREG_STALL_DESTINATION                                           12 : 8
+#define GCREG_STALL_DESTINATION_End                                           12
+#define GCREG_STALL_DESTINATION_Start                                          8
+#define GCREG_STALL_DESTINATION_Type                                         U05
+#define   GCREG_STALL_DESTINATION_FRONT_END                                 0x01
+#define   GCREG_STALL_DESTINATION_PIXEL_ENGINE                              0x07
+#define   GCREG_STALL_DESTINATION_DRAWING_ENGINE                            0x0B
+
+/*******************************************************************************
+** State gcregPipeSelect
+*/
+
+/* Select the current graphics pipe. */
+
+#define gcregPipeSelectRegAddrs                                           0x0E00
+#define GCREG_PIPE_SELECT_MSB                                                 15
+#define GCREG_PIPE_SELECT_LSB                                                  0
+#define GCREG_PIPE_SELECT_BLK                                                  0
+#define GCREG_PIPE_SELECT_Count                                                1
+#define GCREG_PIPE_SELECT_FieldMask                                   0x00000001
+#define GCREG_PIPE_SELECT_ReadMask                                    0x00000001
+#define GCREG_PIPE_SELECT_WriteMask                                   0x00000001
+#define GCREG_PIPE_SELECT_ResetValue                                  0x00000000
+
+/* Selects the pipe to send states and data to.  Make  sure the PE is idle    **
+** before you switch pipes.                                                   */
+#define GCREG_PIPE_SELECT_PIPE                                             0 : 0
+#define GCREG_PIPE_SELECT_PIPE_End                                             0
+#define GCREG_PIPE_SELECT_PIPE_Start                                           0
+#define GCREG_PIPE_SELECT_PIPE_Type                                          U01
+#define   GCREG_PIPE_SELECT_PIPE_PIPE3D                                      0x0
+#define   GCREG_PIPE_SELECT_PIPE_PIPE2D                                      0x1
+
+struct gcregpipeselect {
+	/* gcregPipeSelectRegAddrs:GCREG_PIPE_SELECT_PIPE */
+	unsigned int pipe:1;
+
+	/* gcregPipeSelectRegAddrs:reserved */
+	unsigned int _reserved_1_31:31;
+};
+
+static const struct gcregpipeselect gcregpipeselect_2D = {
+	/* gcregPipeSelectRegAddrs:GCREG_PIPE_SELECT_PIPE */
+	GCREG_PIPE_SELECT_PIPE_PIPE2D,
+
+	/* gcregPipeSelectRegAddrs:reserved */
+	0
+};
+
+static const struct gcregpipeselect gcregpipeselect_3D = {
+	/* gcregPipeSelectRegAddrs:GCREG_PIPE_SELECT_PIPE */
+	GCREG_PIPE_SELECT_PIPE_PIPE3D,
+
+	/* gcregPipeSelectRegAddrs:reserved */
+	0
+};
+
+/*******************************************************************************
+** State gcregEvent
+*/
+
+/* Send an event. */
+
+#define gcregEventRegAddrs                                                0x0E01
+#define GCREG_EVENT_MSB                                                       15
+#define GCREG_EVENT_LSB                                                        0
+#define GCREG_EVENT_BLK                                                        0
+#define GCREG_EVENT_Count                                                      1
+#define GCREG_EVENT_FieldMask                                         0x0000007F
+#define GCREG_EVENT_ReadMask                                          0x0000007F
+#define GCREG_EVENT_WriteMask                                         0x0000007F
+#define GCREG_EVENT_ResetValue                                        0x00000000
+
+/* 5-bit event ID to send. */
+#define GCREG_EVENT_EVENT_ID                                               4 : 0
+#define GCREG_EVENT_EVENT_ID_End                                               4
+#define GCREG_EVENT_EVENT_ID_Start                                             0
+#define GCREG_EVENT_EVENT_ID_Type                                            U05
+
+/* The event is sent by the FE. */
+#define GCREG_EVENT_FE_SRC                                                 5 : 5
+#define GCREG_EVENT_FE_SRC_End                                                 5
+#define GCREG_EVENT_FE_SRC_Start                                               5
+#define GCREG_EVENT_FE_SRC_Type                                              U01
+#define   GCREG_EVENT_FE_SRC_DISABLE                                         0x0
+#define   GCREG_EVENT_FE_SRC_ENABLE                                          0x1
+
+/* The event is sent by the PE. */
+#define GCREG_EVENT_PE_SRC                                                 6 : 6
+#define GCREG_EVENT_PE_SRC_End                                                 6
+#define GCREG_EVENT_PE_SRC_Start                                               6
+#define GCREG_EVENT_PE_SRC_Type                                              U01
+#define   GCREG_EVENT_PE_SRC_DISABLE                                         0x0
+#define   GCREG_EVENT_PE_SRC_ENABLE                                          0x1
+
+struct gcregevent {
+	/* gcregEventRegAddrs:GCREG_EVENT_EVENT_ID */
+	unsigned int id:5;
+
+	/* gcregEventRegAddrs:GCREG_EVENT_FE_SRC */
+	unsigned int fe:1;
+
+	/* gcregEventRegAddrs:GCREG_EVENT_PE_SRC */
+	unsigned int pe:1;
+
+	/* gcregEventRegAddrs:reserved */
+	unsigned int _reserved_7_31:25;
+};
+
+/*******************************************************************************
+** State gcregSemaphore
+*/
+
+/* A sempahore state arms the semaphore in the destination. */
+
+#define gcregSemaphoreRegAddrs                                            0x0E02
+#define GCREG_SEMAPHORE_MSB                                                   15
+#define GCREG_SEMAPHORE_LSB                                                    0
+#define GCREG_SEMAPHORE_BLK                                                    0
+#define GCREG_SEMAPHORE_Count                                                  1
+#define GCREG_SEMAPHORE_FieldMask                                     0x00001F1F
+#define GCREG_SEMAPHORE_ReadMask                                      0x00001F1F
+#define GCREG_SEMAPHORE_WriteMask                                     0x00001F1F
+#define GCREG_SEMAPHORE_ResetValue                                    0x00000000
+
+#define GCREG_SEMAPHORE_SOURCE                                             4 : 0
+#define GCREG_SEMAPHORE_SOURCE_End                                             4
+#define GCREG_SEMAPHORE_SOURCE_Start                                           0
+#define GCREG_SEMAPHORE_SOURCE_Type                                          U05
+#define   GCREG_SEMAPHORE_SOURCE_FRONT_END                                  0x01
+#define   GCREG_SEMAPHORE_SOURCE_PIXEL_ENGINE                               0x07
+#define   GCREG_SEMAPHORE_SOURCE_DRAWING_ENGINE                             0x0B
+
+#define GCREG_SEMAPHORE_DESTINATION                                       12 : 8
+#define GCREG_SEMAPHORE_DESTINATION_End                                       12
+#define GCREG_SEMAPHORE_DESTINATION_Start                                      8
+#define GCREG_SEMAPHORE_DESTINATION_Type                                     U05
+#define   GCREG_SEMAPHORE_DESTINATION_FRONT_END                             0x01
+#define   GCREG_SEMAPHORE_DESTINATION_PIXEL_ENGINE                          0x07
+#define   GCREG_SEMAPHORE_DESTINATION_DRAWING_ENGINE                        0x0B
+
+struct gcregsemaphore {
+	/* gcregSemaphoreRegAddrs:GCREG_SEMAPHORE_SOURCE */
+	unsigned int src:5;
+
+	/* gcregSemaphoreRegAddrs:reserved */
+	unsigned int _reserved_5_7:3;
+
+	/* gcregSemaphoreRegAddrs:GCREG_SEMAPHORE_DESTINATION */
+	unsigned int dst:5;
+
+	/* gcregSemaphoreRegAddrs:reserved */
+	unsigned int _reserved_13_31:19;
+};
+
+static const struct gcregsemaphore gcregsema_fe_pe = {
+	/* gcregSemaphoreRegAddrs:GCREG_SEMAPHORE_SOURCE */
+	GCREG_SEMAPHORE_SOURCE_FRONT_END,
+
+	/* gcregSemaphoreRegAddrs:reserved */
+	0,
+
+	/* gcregSemaphoreRegAddrs:GCREG_SEMAPHORE_DESTINATION */
+	GCREG_SEMAPHORE_DESTINATION_PIXEL_ENGINE,
+
+	/* gcregSemaphoreRegAddrs:reserved */
+	0
+};
+
+
+/*******************************************************************************
+** State gcregFlush
+*/
+
+/* Flush the current pipe. */
+
+#define gcregFlushRegAddrs                                                0x0E03
+#define GCREG_FLUSH_MSB                                                       15
+#define GCREG_FLUSH_LSB                                                        0
+#define GCREG_FLUSH_BLK                                                        0
+#define GCREG_FLUSH_Count                                                      1
+#define GCREG_FLUSH_FieldMask                                         0x00000008
+#define GCREG_FLUSH_ReadMask                                          0x00000008
+#define GCREG_FLUSH_WriteMask                                         0x00000008
+#define GCREG_FLUSH_ResetValue                                        0x00000000
+
+/* Flush the 2D pixel cache. */
+#define GCREG_FLUSH_PE2D_CACHE                                             3 : 3
+#define GCREG_FLUSH_PE2D_CACHE_End                                             3
+#define GCREG_FLUSH_PE2D_CACHE_Start                                           3
+#define GCREG_FLUSH_PE2D_CACHE_Type                                          U01
+#define   GCREG_FLUSH_PE2D_CACHE_DISABLE                                     0x0
+#define   GCREG_FLUSH_PE2D_CACHE_ENABLE                                      0x1
+
+struct gcregflush {
+	/* gcregFlushRegAddrs:reserved */
+	unsigned int _reserved_0_2:3;
+
+	/* gcregFlushRegAddrs:GCREG_FLUSH_PE2D_CACHE */
+	unsigned int enable:1;
+
+	/* gcregFlushRegAddrs:reserved */
+	unsigned int _reserved_4_31:28;
+};
+
+static const struct gcregflush gcregflush_pe2D = {
+	/* gcregFlushRegAddrs:reserved */
+	0,
+
+	/* gcregFlushRegAddrs:GCREG_FLUSH_PE2D_CACHE */
+	GCREG_FLUSH_PE2D_CACHE_ENABLE,
+
+	/* gcregFlushRegAddrs:reserved */
+	0
+};
+
+/*******************************************************************************
+** State gcregMMUFlush
+*/
+
+/* Flush the virtual addrses lookup cache inside the MC. */
+
+#define gcregMMUFlushRegAddrs                                             0x0E04
+#define gcregMMU_FLUSH_MSB                                                    15
+#define gcregMMU_FLUSH_LSB                                                     0
+#define gcregMMU_FLUSH_BLK                                                     0
+#define gcregMMU_FLUSH_Count                                                   1
+#define gcregMMU_FLUSH_FieldMask                                      0x00000009
+#define gcregMMU_FLUSH_ReadMask                                       0x00000009
+#define gcregMMU_FLUSH_WriteMask                                      0x00000009
+#define gcregMMU_FLUSH_ResetValue                                     0x00000000
+
+/* Flush the FE address translation caches. */
+#define gcregMMU_FLUSH_FEMMU                                               0 : 0
+#define gcregMMU_FLUSH_FEMMU_End                                               0
+#define gcregMMU_FLUSH_FEMMU_Start                                             0
+#define gcregMMU_FLUSH_FEMMU_Type                                            U01
+#define   gcregMMU_FLUSH_FEMMU_DISABLE                                       0x0
+#define   gcregMMU_FLUSH_FEMMU_ENABLE                                        0x1
+
+/* Flush the PE render target address translation caches. */
+#define gcregMMU_FLUSH_PEMMU                                               3 : 3
+#define gcregMMU_FLUSH_PEMMU_End                                               3
+#define gcregMMU_FLUSH_PEMMU_Start                                             3
+#define gcregMMU_FLUSH_PEMMU_Type                                            U01
+#define   gcregMMU_FLUSH_PEMMU_DISABLE                                       0x0
+#define   gcregMMU_FLUSH_PEMMU_ENABLE                                        0x1
+
+/*******************************************************************************
+** Register gcregCmdBufferAddr
+*/
+
+/* Base address for the command buffer.  The address must be 64-bit aligned
+** and it is always physical. This register cannot be read. To check the value
+** of the current fetch address use gcregFEDebugCurCmdAdr. Since this is a write
+** only register is has no reset value.
+*/
+
+#define GCREG_CMD_BUFFER_ADDR_Address                                    0x00654
+#define GCREG_CMD_BUFFER_ADDR_MSB                                             15
+#define GCREG_CMD_BUFFER_ADDR_LSB                                              0
+#define GCREG_CMD_BUFFER_ADDR_BLK                                              0
+#define GCREG_CMD_BUFFER_ADDR_Count                                            1
+#define GCREG_CMD_BUFFER_ADDR_FieldMask                               0xFFFFFFFF
+#define GCREG_CMD_BUFFER_ADDR_ReadMask                                0x00000000
+#define GCREG_CMD_BUFFER_ADDR_WriteMask                               0xFFFFFFFC
+#define GCREG_CMD_BUFFER_ADDR_ResetValue                              0x00000000
+
+#define GCREG_CMD_BUFFER_ADDR_ADDRESS                                     31 : 0
+#define GCREG_CMD_BUFFER_ADDR_ADDRESS_End                                     30
+#define GCREG_CMD_BUFFER_ADDR_ADDRESS_Start                                    0
+#define GCREG_CMD_BUFFER_ADDR_ADDRESS_Type                                   U31
+
+/*******************************************************************************
+** Register gcregCmdBufferCtrl
+*/
+
+/* Since this is a write only register is has no reset value. */
+
+#define GCREG_CMD_BUFFER_CTRL_Address                                    0x00658
+#define GCREG_CMD_BUFFER_CTRL_MSB                                             15
+#define GCREG_CMD_BUFFER_CTRL_LSB                                              0
+#define GCREG_CMD_BUFFER_CTRL_BLK                                              0
+#define GCREG_CMD_BUFFER_CTRL_Count                                            1
+#define GCREG_CMD_BUFFER_CTRL_FieldMask                               0x0001FFFF
+#define GCREG_CMD_BUFFER_CTRL_ReadMask                                0x00010000
+#define GCREG_CMD_BUFFER_CTRL_WriteMask                               0x0001FFFF
+#define GCREG_CMD_BUFFER_CTRL_ResetValue                              0x00000000
+
+/* Number of 64-bit words to fetch from the command buffer. */
+#define GCREG_CMD_BUFFER_CTRL_PREFETCH                                    15 : 0
+#define GCREG_CMD_BUFFER_CTRL_PREFETCH_End                                    15
+#define GCREG_CMD_BUFFER_CTRL_PREFETCH_Start                                   0
+#define GCREG_CMD_BUFFER_CTRL_PREFETCH_Type                                  U16
+
+/* Enable the command parser. */
+#define GCREG_CMD_BUFFER_CTRL_ENABLE                                     16 : 16
+#define GCREG_CMD_BUFFER_CTRL_ENABLE_End                                      16
+#define GCREG_CMD_BUFFER_CTRL_ENABLE_Start                                    16
+#define GCREG_CMD_BUFFER_CTRL_ENABLE_Type                                    U01
+#define   GCREG_CMD_BUFFER_CTRL_ENABLE_DISABLE                               0x0
+#define   GCREG_CMD_BUFFER_CTRL_ENABLE_ENABLE                                0x1
+
+/*******************************************************************************
+** Register gcregFEDebugState
+*/
+
+#define GCREG_FE_DEBUG_STATE_Address                                     0x00660
+#define GCREG_FE_DEBUG_STATE_MSB                                              15
+#define GCREG_FE_DEBUG_STATE_LSB                                               0
+#define GCREG_FE_DEBUG_STATE_BLK                                               0
+#define GCREG_FE_DEBUG_STATE_Count                                             1
+#define GCREG_FE_DEBUG_STATE_FieldMask                                0x0003FF1F
+#define GCREG_FE_DEBUG_STATE_ReadMask                                 0x0003FF1F
+#define GCREG_FE_DEBUG_STATE_WriteMask                                0x00000000
+#define GCREG_FE_DEBUG_STATE_ResetValue                               0x00000000
+
+#define GCREG_FE_DEBUG_STATE_CMD_STATE                                     4 : 0
+#define GCREG_FE_DEBUG_STATE_CMD_STATE_End                                     4
+#define GCREG_FE_DEBUG_STATE_CMD_STATE_Start                                   0
+#define GCREG_FE_DEBUG_STATE_CMD_STATE_Type                                  U05
+
+#define GCREG_FE_DEBUG_STATE_CMD_DMA_STATE                                 9 : 8
+#define GCREG_FE_DEBUG_STATE_CMD_DMA_STATE_End                                 9
+#define GCREG_FE_DEBUG_STATE_CMD_DMA_STATE_Start                               8
+#define GCREG_FE_DEBUG_STATE_CMD_DMA_STATE_Type                              U02
+
+#define GCREG_FE_DEBUG_STATE_CMD_FETCH_STATE                             11 : 10
+#define GCREG_FE_DEBUG_STATE_CMD_FETCH_STATE_End                              11
+#define GCREG_FE_DEBUG_STATE_CMD_FETCH_STATE_Start                            10
+#define GCREG_FE_DEBUG_STATE_CMD_FETCH_STATE_Type                            U02
+
+#define GCREG_FE_DEBUG_STATE_REQ_DMA_STATE                               13 : 12
+#define GCREG_FE_DEBUG_STATE_REQ_DMA_STATE_End                                13
+#define GCREG_FE_DEBUG_STATE_REQ_DMA_STATE_Start                              12
+#define GCREG_FE_DEBUG_STATE_REQ_DMA_STATE_Type                              U02
+
+#define GCREG_FE_DEBUG_STATE_CAL_STATE                                   15 : 14
+#define GCREG_FE_DEBUG_STATE_CAL_STATE_End                                    15
+#define GCREG_FE_DEBUG_STATE_CAL_STATE_Start                                  14
+#define GCREG_FE_DEBUG_STATE_CAL_STATE_Type                                  U02
+
+#define GCREG_FE_DEBUG_STATE_VE_REQ_STATE                                17 : 16
+#define GCREG_FE_DEBUG_STATE_VE_REQ_STATE_End                                 17
+#define GCREG_FE_DEBUG_STATE_VE_REQ_STATE_Start                               16
+#define GCREG_FE_DEBUG_STATE_VE_REQ_STATE_Type                               U02
+
+/*******************************************************************************
+** Register gcregFEDebugCurCmdAdr
+*/
+
+/* This is the command decoder address.  The address is always physical so
+** the MSB should always be 0.  It has no reset value.
+*/
+
+#define GCREG_FE_DEBUG_CUR_CMD_ADR_Address                               0x00664
+#define GCREG_FE_DEBUG_CUR_CMD_ADR_MSB                                        15
+#define GCREG_FE_DEBUG_CUR_CMD_ADR_LSB                                         0
+#define GCREG_FE_DEBUG_CUR_CMD_ADR_BLK                                         0
+#define GCREG_FE_DEBUG_CUR_CMD_ADR_Count                                       1
+#define GCREG_FE_DEBUG_CUR_CMD_ADR_FieldMask                          0xFFFFFFF8
+#define GCREG_FE_DEBUG_CUR_CMD_ADR_ReadMask                           0xFFFFFFF8
+#define GCREG_FE_DEBUG_CUR_CMD_ADR_WriteMask                          0x00000000
+#define GCREG_FE_DEBUG_CUR_CMD_ADR_ResetValue                         0x00000000
+
+#define GCREG_FE_DEBUG_CUR_CMD_ADR_CUR_CMD_ADR                            31 : 3
+#define GCREG_FE_DEBUG_CUR_CMD_ADR_CUR_CMD_ADR_End                            31
+#define GCREG_FE_DEBUG_CUR_CMD_ADR_CUR_CMD_ADR_Start                           3
+#define GCREG_FE_DEBUG_CUR_CMD_ADR_CUR_CMD_ADR_Type                          U29
+
+/*******************************************************************************
+** Register gcregFEDebugCmdLowReg
+*/
+
+#define GCREG_FE_DEBUG_CMD_LOW_REG_Address                               0x00668
+#define GCREG_FE_DEBUG_CMD_LOW_REG_MSB                                        15
+#define GCREG_FE_DEBUG_CMD_LOW_REG_LSB                                         0
+#define GCREG_FE_DEBUG_CMD_LOW_REG_BLK                                         0
+#define GCREG_FE_DEBUG_CMD_LOW_REG_Count                                       1
+#define GCREG_FE_DEBUG_CMD_LOW_REG_FieldMask                          0xFFFFFFFF
+#define GCREG_FE_DEBUG_CMD_LOW_REG_ReadMask                           0xFFFFFFFF
+#define GCREG_FE_DEBUG_CMD_LOW_REG_WriteMask                          0x00000000
+#define GCREG_FE_DEBUG_CMD_LOW_REG_ResetValue                         0x00000000
+
+/* Command register used by CmdState. */
+#define GCREG_FE_DEBUG_CMD_LOW_REG_CMD_LOW_REG                            31 : 0
+#define GCREG_FE_DEBUG_CMD_LOW_REG_CMD_LOW_REG_End                            31
+#define GCREG_FE_DEBUG_CMD_LOW_REG_CMD_LOW_REG_Start                           0
+#define GCREG_FE_DEBUG_CMD_LOW_REG_CMD_LOW_REG_Type                          U32
+
+/*******************************************************************************
+** Register gcregFEDebugCmdHiReg
+*/
+
+#define GCREG_FE_DEBUG_CMD_HI_REG_Address                                0x0066C
+#define GCREG_FE_DEBUG_CMD_HI_REG_MSB                                         15
+#define GCREG_FE_DEBUG_CMD_HI_REG_LSB                                          0
+#define GCREG_FE_DEBUG_CMD_HI_REG_BLK                                          0
+#define GCREG_FE_DEBUG_CMD_HI_REG_Count                                        1
+#define GCREG_FE_DEBUG_CMD_HI_REG_FieldMask                           0xFFFFFFFF
+#define GCREG_FE_DEBUG_CMD_HI_REG_ReadMask                            0xFFFFFFFF
+#define GCREG_FE_DEBUG_CMD_HI_REG_WriteMask                           0x00000000
+#define GCREG_FE_DEBUG_CMD_HI_REG_ResetValue                          0x00000000
+
+/* Command register used by CmdState. */
+#define GCREG_FE_DEBUG_CMD_HI_REG_CMD_HI_REG                              31 : 0
+#define GCREG_FE_DEBUG_CMD_HI_REG_CMD_HI_REG_End                              31
+#define GCREG_FE_DEBUG_CMD_HI_REG_CMD_HI_REG_Start                             0
+#define GCREG_FE_DEBUG_CMD_HI_REG_CMD_HI_REG_Type                            U32
+
+/*******************************************************************************
+** State gcregMMUSafeAddress
+*/
+
+/* A 64-byte address that will acts as a 'safe' zone.  Any address that would
+** cause an exception is routed to this safe zone.  Reads will happend and
+** writes will go to this address, but with a write-enable of 0. This
+** register can only be programmed once after a reset - any attempt to write
+** to this register after the initial write-after-reset will be ignored.
+*/
+
+#define gcregMMUSafeAddressRegAddrs                                       0x0060
+#define GCREG_MMU_SAFE_ADDRESS_MSB                                            15
+#define GCREG_MMU_SAFE_ADDRESS_LSB                                             0
+#define GCREG_MMU_SAFE_ADDRESS_BLK                                             0
+#define GCREG_MMU_SAFE_ADDRESS_Count                                           1
+#define GCREG_MMU_SAFE_ADDRESS_FieldMask                              0xFFFFFFFF
+#define GCREG_MMU_SAFE_ADDRESS_ReadMask                               0xFFFFFFC0
+#define GCREG_MMU_SAFE_ADDRESS_WriteMask                              0xFFFFFFC0
+#define GCREG_MMU_SAFE_ADDRESS_ResetValue                             0x00000000
+
+#define GCREG_MMU_SAFE_ADDRESS_ADDRESS                                    31 : 0
+#define GCREG_MMU_SAFE_ADDRESS_ADDRESS_End                                    31
+#define GCREG_MMU_SAFE_ADDRESS_ADDRESS_Start                                   0
+#define GCREG_MMU_SAFE_ADDRESS_ADDRESS_Type                                  U32
+
+/*******************************************************************************
+** State gcregMMUConfiguration
+*/
+
+/* This register controls the master TLB of the MMU. */
+
+#define gcregMMUConfigurationRegAddrs                                     0x0061
+#define GCREG_MMU_CONFIGURATION_MSB                                           15
+#define GCREG_MMU_CONFIGURATION_LSB                                            0
+#define GCREG_MMU_CONFIGURATION_BLK                                            0
+#define GCREG_MMU_CONFIGURATION_Count                                          1
+#define GCREG_MMU_CONFIGURATION_FieldMask                             0xFFFFFD99
+#define GCREG_MMU_CONFIGURATION_ReadMask                              0xFFFFFD99
+#define GCREG_MMU_CONFIGURATION_WriteMask                             0xFFFFFD99
+#define GCREG_MMU_CONFIGURATION_ResetValue                            0x00000000
+
+/* Upper bits of the page aligned (depending on the mode) master TLB. */
+#define GCREG_MMU_CONFIGURATION_ADDRESS                                  31 : 10
+#define GCREG_MMU_CONFIGURATION_ADDRESS_End                                   31
+#define GCREG_MMU_CONFIGURATION_ADDRESS_Start                                 10
+#define GCREG_MMU_CONFIGURATION_ADDRESS_Type                                 U22
+
+/* Mask for Address field. */
+#define GCREG_MMU_CONFIGURATION_MASK_ADDRESS                               8 : 8
+#define GCREG_MMU_CONFIGURATION_MASK_ADDRESS_End                               8
+#define GCREG_MMU_CONFIGURATION_MASK_ADDRESS_Start                             8
+#define GCREG_MMU_CONFIGURATION_MASK_ADDRESS_Type                            U01
+#define   GCREG_MMU_CONFIGURATION_MASK_ADDRESS_ENABLED                       0x0
+#define   GCREG_MMU_CONFIGURATION_MASK_ADDRESS_MASKED                        0x1
+
+/* Mask Flush field. */
+#define GCREG_MMU_CONFIGURATION_MASK_FLUSH                                 7 : 7
+#define GCREG_MMU_CONFIGURATION_MASK_FLUSH_End                                 7
+#define GCREG_MMU_CONFIGURATION_MASK_FLUSH_Start                               7
+#define GCREG_MMU_CONFIGURATION_MASK_FLUSH_Type                              U01
+#define   GCREG_MMU_CONFIGURATION_MASK_FLUSH_ENABLED                         0x0
+#define   GCREG_MMU_CONFIGURATION_MASK_FLUSH_MASKED                          0x1
+
+/* Flush the MMU caches. */
+#define GCREG_MMU_CONFIGURATION_FLUSH                                      4 : 4
+#define GCREG_MMU_CONFIGURATION_FLUSH_End                                      4
+#define GCREG_MMU_CONFIGURATION_FLUSH_Start                                    4
+#define GCREG_MMU_CONFIGURATION_FLUSH_Type                                   U01
+#define   GCREG_MMU_CONFIGURATION_FLUSH_FLUSH                                0x1
+
+/* Mask Mode field. */
+#define GCREG_MMU_CONFIGURATION_MASK_MODE                                  3 : 3
+#define GCREG_MMU_CONFIGURATION_MASK_MODE_End                                  3
+#define GCREG_MMU_CONFIGURATION_MASK_MODE_Start                                3
+#define GCREG_MMU_CONFIGURATION_MASK_MODE_Type                               U01
+#define   GCREG_MMU_CONFIGURATION_MASK_MODE_ENABLED                          0x0
+#define   GCREG_MMU_CONFIGURATION_MASK_MODE_MASKED                           0x1
+
+/* Set the mode for the Master TLB. */
+#define GCREG_MMU_CONFIGURATION_MODE                                       0 : 0
+#define GCREG_MMU_CONFIGURATION_MODE_End                                       0
+#define GCREG_MMU_CONFIGURATION_MODE_Start                                     0
+#define GCREG_MMU_CONFIGURATION_MODE_Type                                    U01
+/* The Master TLB is 4kB in size and contains 1024 entries. Each page can be  **
+** 4kB or 64kB in size.                                                       */
+#define   GCREG_MMU_CONFIGURATION_MODE_MODE4_K                               0x0
+/* The Master TLB is 1kB in size and contains 256 entries. Each page can be   **
+** 4kB, 64kB, 1MB or 16MB in size.                                            */
+#define   GCREG_MMU_CONFIGURATION_MODE_MODE1_K                               0x1
+
+struct gcregmmuconfiguration {
+	/* gcregMMUConfiguration:GCREG_MMU_CONFIGURATION_MODE */
+	unsigned int master:1;
+
+	/* gcregMMUConfiguration:reserved */
+	unsigned int _reserved_1_2:2;
+
+	/* gcregMMUConfiguration:GCREG_MMU_CONFIGURATION_MASK_MODE */
+	unsigned int master_mask:1;
+
+	/* gcregMMUConfiguration:GCREG_MMU_CONFIGURATION_FLUSH */
+	unsigned int flush:1;
+
+	/* gcregMMUConfiguration:reserved */
+	unsigned int _reserved_5_6:2;
+
+	/* gcregMMUConfiguration:GCREG_MMU_CONFIGURATION_MASK_FLUSH */
+	unsigned int flush_mask:1;
+
+	/* gcregMMUConfiguration:GCREG_MMU_CONFIGURATION_MASK_ADDRESS */
+	unsigned int address_mask:1;
+
+	/* gcregMMUConfiguration:reserved */
+	unsigned int _reserved_9:1;
+
+	/* gcregMMUConfiguration:GCREG_MMU_CONFIGURATION_ADDRESS */
+	unsigned int address:22;
+};
+
+static const struct gcregmmuconfiguration gcregmmu_flush = {
+	/* gcregMMUConfiguration:GCREG_MMU_CONFIGURATION_MODE */
+	0,
+
+	/* gcregMMUConfiguration:reserved */
+	0,
+
+	/* gcregMMUConfiguration:GCREG_MMU_CONFIGURATION_MASK_MODE */
+	GCREG_MMU_CONFIGURATION_MASK_MODE_MASKED,
+
+	/* gcregMMUConfiguration:GCREG_MMU_CONFIGURATION_FLUSH */
+	GCREG_MMU_CONFIGURATION_FLUSH_FLUSH,
+
+	/* gcregMMUConfiguration:reserved */
+	0,
+
+	/* gcregMMUConfiguration:GCREG_MMU_CONFIGURATION_MASK_FLUSH */
+	GCREG_MMU_CONFIGURATION_MASK_FLUSH_ENABLED,
+
+	/* gcregMMUConfiguration:GCREG_MMU_CONFIGURATION_MASK_ADDRESS */
+	GCREG_MMU_CONFIGURATION_MASK_ADDRESS_MASKED,
+
+	/* gcregMMUConfiguration:reserved */
+	0,
+
+	/* gcregMMUConfiguration:GCREG_MMU_CONFIGURATION_ADDRESS */
+	0
+};
+
+/*******************************************************************************
+** Register gcregMMUStatus
+*/
+
+/* Status register that holds which MMU generated an exception. */
+
+#define GCREG_MMU_STATUS_Address                                         0x00188
+#define GCREG_MMU_STATUS_MSB                                                  15
+#define GCREG_MMU_STATUS_LSB                                                   0
+#define GCREG_MMU_STATUS_BLK                                                   0
+#define GCREG_MMU_STATUS_Count                                                 1
+#define GCREG_MMU_STATUS_FieldMask                                    0x00003333
+#define GCREG_MMU_STATUS_ReadMask                                     0x00003333
+#define GCREG_MMU_STATUS_WriteMask                                    0x00000000
+#define GCREG_MMU_STATUS_ResetValue                                   0x00000000
+
+/* MMU 3 caused an exception and the fourth gcregMMUException register holds  **
+** the offending address.                                                     */
+#define GCREG_MMU_STATUS_EXCEPTION3                                      13 : 12
+#define GCREG_MMU_STATUS_EXCEPTION3_End                                       13
+#define GCREG_MMU_STATUS_EXCEPTION3_Start                                     12
+#define GCREG_MMU_STATUS_EXCEPTION3_Type                                     U02
+#define   GCREG_MMU_STATUS_EXCEPTION3_SLAVE_NOT_PRESENT                      0x1
+#define   GCREG_MMU_STATUS_EXCEPTION3_PAGE_NOT_PRESENT                       0x2
+#define   GCREG_MMU_STATUS_EXCEPTION3_WRITE_VIOLATION                        0x3
+
+/* MMU 2 caused an exception and the third gcregMMUException register holds   **
+** the offending address.                                                     */
+#define GCREG_MMU_STATUS_EXCEPTION2                                        9 : 8
+#define GCREG_MMU_STATUS_EXCEPTION2_End                                        9
+#define GCREG_MMU_STATUS_EXCEPTION2_Start                                      8
+#define GCREG_MMU_STATUS_EXCEPTION2_Type                                     U02
+#define   GCREG_MMU_STATUS_EXCEPTION2_SLAVE_NOT_PRESENT                      0x1
+#define   GCREG_MMU_STATUS_EXCEPTION2_PAGE_NOT_PRESENT                       0x2
+#define   GCREG_MMU_STATUS_EXCEPTION2_WRITE_VIOLATION                        0x3
+
+/* MMU 1 caused an exception and the second gcregMMUException register holds  **
+** the offending address.                                                     */
+#define GCREG_MMU_STATUS_EXCEPTION1                                        5 : 4
+#define GCREG_MMU_STATUS_EXCEPTION1_End                                        5
+#define GCREG_MMU_STATUS_EXCEPTION1_Start                                      4
+#define GCREG_MMU_STATUS_EXCEPTION1_Type                                     U02
+#define   GCREG_MMU_STATUS_EXCEPTION1_SLAVE_NOT_PRESENT                      0x1
+#define   GCREG_MMU_STATUS_EXCEPTION1_PAGE_NOT_PRESENT                       0x2
+#define   GCREG_MMU_STATUS_EXCEPTION1_WRITE_VIOLATION                        0x3
+
+/* MMU 0 caused an exception and the first gcregMMUException register holds   **
+** the offending address.                                                     */
+#define GCREG_MMU_STATUS_EXCEPTION0                                        1 : 0
+#define GCREG_MMU_STATUS_EXCEPTION0_End                                        1
+#define GCREG_MMU_STATUS_EXCEPTION0_Start                                      0
+#define GCREG_MMU_STATUS_EXCEPTION0_Type                                     U02
+#define   GCREG_MMU_STATUS_EXCEPTION0_SLAVE_NOT_PRESENT                      0x1
+#define   GCREG_MMU_STATUS_EXCEPTION0_PAGE_NOT_PRESENT                       0x2
+#define   GCREG_MMU_STATUS_EXCEPTION0_WRITE_VIOLATION                        0x3
+
+/*******************************************************************************
+** Register gcregMMUControl
+*/
+
+/* Control register that enables the MMU (only time shot). */
+
+#define GCREG_MMU_CONTROL_Address                                        0x0018C
+#define GCREG_MMU_CONTROL_MSB                                                 15
+#define GCREG_MMU_CONTROL_LSB                                                  0
+#define GCREG_MMU_CONTROL_BLK                                                  0
+#define GCREG_MMU_CONTROL_Count                                                1
+#define GCREG_MMU_CONTROL_FieldMask                                   0x00000001
+#define GCREG_MMU_CONTROL_ReadMask                                    0x00000000
+#define GCREG_MMU_CONTROL_WriteMask                                   0x00000001
+#define GCREG_MMU_CONTROL_ResetValue                                  0x00000000
+
+/* Enable the MMU. For security reasons, once the MMU is  enabled it cannot   **
+** be disabled anymore.                                                       */
+#define GCREG_MMU_CONTROL_ENABLE                                           0 : 0
+#define GCREG_MMU_CONTROL_ENABLE_End                                           0
+#define GCREG_MMU_CONTROL_ENABLE_Start                                         0
+#define GCREG_MMU_CONTROL_ENABLE_Type                                        U01
+#define   GCREG_MMU_CONTROL_ENABLE_ENABLE                                    0x1
+
+/*******************************************************************************
+** State/Register gcregMMUException (4 in total)
+*/
+
+/* Up to 4 registers that will hold the original address that generated an
+** exception. Use load state form for exception resolution.
+*/
+
+#define gcregMMUExceptionRegAddrs                                         0x0064
+#define GCREG_MMU_EXCEPTION_Address                                      0x00190
+#define GCREG_MMU_EXCEPTION_MSB                                               15
+#define GCREG_MMU_EXCEPTION_LSB                                                2
+#define GCREG_MMU_EXCEPTION_BLK                                                2
+#define GCREG_MMU_EXCEPTION_Count                                              4
+#define GCREG_MMU_EXCEPTION_FieldMask                                 0xFFFFFFFF
+#define GCREG_MMU_EXCEPTION_ReadMask                                  0xFFFFFFFF
+#define GCREG_MMU_EXCEPTION_WriteMask                                 0xFFFFFFFF
+#define GCREG_MMU_EXCEPTION_ResetValue                                0x00000000
+
+#define GCREG_MMU_EXCEPTION_ADDRESS                                       31 : 0
+#define GCREG_MMU_EXCEPTION_ADDRESS_End                                       31
+#define GCREG_MMU_EXCEPTION_ADDRESS_Start                                      0
+#define GCREG_MMU_EXCEPTION_ADDRESS_Type                                     U32
+
+/*******************************************************************************
+** Register gcModulePowerControls
+*/
+
+/* Control register for module level power controls. */
+
+#define GC_MODULE_POWER_CONTROLS_Address                                 0x00100
+#define GC_MODULE_POWER_CONTROLS_MSB                                          15
+#define GC_MODULE_POWER_CONTROLS_LSB                                           0
+#define GC_MODULE_POWER_CONTROLS_BLK                                           0
+#define GC_MODULE_POWER_CONTROLS_Count                                         1
+#define GC_MODULE_POWER_CONTROLS_FieldMask                            0xFFFF00F7
+#define GC_MODULE_POWER_CONTROLS_ReadMask                             0xFFFF00F7
+#define GC_MODULE_POWER_CONTROLS_WriteMask                            0xFFFF00F7
+#define GC_MODULE_POWER_CONTROLS_ResetValue                           0x00140020
+
+/* Enables module level clock gating. */
+#define GC_MODULE_POWER_CONTROLS_ENABLE_MODULE_CLOCK_GATING                0 : 0
+#define GC_MODULE_POWER_CONTROLS_ENABLE_MODULE_CLOCK_GATING_End                0
+#define GC_MODULE_POWER_CONTROLS_ENABLE_MODULE_CLOCK_GATING_Start              0
+#define GC_MODULE_POWER_CONTROLS_ENABLE_MODULE_CLOCK_GATING_Type             U01
+
+/* Disables module level clock gating for stall condition. */
+#define GC_MODULE_POWER_CONTROLS_DISABLE_STALL_MODULE_CLOCK_GATING         1 : 1
+#define GC_MODULE_POWER_CONTROLS_DISABLE_STALL_MODULE_CLOCK_GATING_End         1
+#define GC_MODULE_POWER_CONTROLS_DISABLE_STALL_MODULE_CLOCK_GATING_Start       1
+#define GC_MODULE_POWER_CONTROLS_DISABLE_STALL_MODULE_CLOCK_GATING_Type      U01
+
+/* Disables module level clock gating for starve/idle condition. */
+#define GC_MODULE_POWER_CONTROLS_DISABLE_STARVE_MODULE_CLOCK_GATING        2 : 2
+#define GC_MODULE_POWER_CONTROLS_DISABLE_STARVE_MODULE_CLOCK_GATING_End        2
+#define GC_MODULE_POWER_CONTROLS_DISABLE_STARVE_MODULE_CLOCK_GATING_Start      2
+#define GC_MODULE_POWER_CONTROLS_DISABLE_STARVE_MODULE_CLOCK_GATING_Type     U01
+
+/* Number of clock cycles to wait after turning on the clock. */
+#define GC_MODULE_POWER_CONTROLS_TURN_ON_COUNTER                           7 : 4
+#define GC_MODULE_POWER_CONTROLS_TURN_ON_COUNTER_End                           7
+#define GC_MODULE_POWER_CONTROLS_TURN_ON_COUNTER_Start                         4
+#define GC_MODULE_POWER_CONTROLS_TURN_ON_COUNTER_Type                        U04
+
+/* Counter value for clock gating the module if the module is idle for  this  **
+** amount of clock cycles.                                                    */
+#define GC_MODULE_POWER_CONTROLS_TURN_OFF_COUNTER                        31 : 16
+#define GC_MODULE_POWER_CONTROLS_TURN_OFF_COUNTER_End                         31
+#define GC_MODULE_POWER_CONTROLS_TURN_OFF_COUNTER_Start                       16
+#define GC_MODULE_POWER_CONTROLS_TURN_OFF_COUNTER_Type                       U16
+
+/*******************************************************************************
+** Register gcModulePowerModuleControl
+*/
+
+/* Module level control registers. */
+
+#define GC_MODULE_POWER_MODULE_CONTROL_Address                           0x00104
+#define GC_MODULE_POWER_MODULE_CONTROL_MSB                                    15
+#define GC_MODULE_POWER_MODULE_CONTROL_LSB                                     0
+#define GC_MODULE_POWER_MODULE_CONTROL_BLK                                     0
+#define GC_MODULE_POWER_MODULE_CONTROL_Count                                   1
+#define GC_MODULE_POWER_MODULE_CONTROL_FieldMask                      0x00000007
+#define GC_MODULE_POWER_MODULE_CONTROL_ReadMask                       0x00000007
+#define GC_MODULE_POWER_MODULE_CONTROL_WriteMask                      0x00000007
+#define GC_MODULE_POWER_MODULE_CONTROL_ResetValue                     0x00000000
+
+/* Disables module level clock gating for FE. */
+#define GC_MODULE_POWER_MODULE_CONTROL_DISABLE_MODULE_CLOCK_GATING_FE      0 : 0
+#define GC_MODULE_POWER_MODULE_CONTROL_DISABLE_MODULE_CLOCK_GATING_FE_End      0
+#define GC_MODULE_POWER_MODULE_CONTROL_DISABLE_MODULE_CLOCK_GATING_FE_Start    0
+#define GC_MODULE_POWER_MODULE_CONTROL_DISABLE_MODULE_CLOCK_GATING_FE_Type   U01
+
+/* Disables module level clock gating for DE. */
+#define GC_MODULE_POWER_MODULE_CONTROL_DISABLE_MODULE_CLOCK_GATING_DE      1 : 1
+#define GC_MODULE_POWER_MODULE_CONTROL_DISABLE_MODULE_CLOCK_GATING_DE_End      1
+#define GC_MODULE_POWER_MODULE_CONTROL_DISABLE_MODULE_CLOCK_GATING_DE_Start    1
+#define GC_MODULE_POWER_MODULE_CONTROL_DISABLE_MODULE_CLOCK_GATING_DE_Type   U01
+
+/* Disables module level clock gating for PE. */
+#define GC_MODULE_POWER_MODULE_CONTROL_DISABLE_MODULE_CLOCK_GATING_PE      2 : 2
+#define GC_MODULE_POWER_MODULE_CONTROL_DISABLE_MODULE_CLOCK_GATING_PE_End      2
+#define GC_MODULE_POWER_MODULE_CONTROL_DISABLE_MODULE_CLOCK_GATING_PE_Start    2
+#define GC_MODULE_POWER_MODULE_CONTROL_DISABLE_MODULE_CLOCK_GATING_PE_Type   U01
+
+/*******************************************************************************
+** Register gcModulePowerModuleStatus
+*/
+
+/* Module level control status. */
+
+#define GC_MODULE_POWER_MODULE_STATUS_Address                            0x00108
+#define GC_MODULE_POWER_MODULE_STATUS_MSB                                     15
+#define GC_MODULE_POWER_MODULE_STATUS_LSB                                      0
+#define GC_MODULE_POWER_MODULE_STATUS_BLK                                      0
+#define GC_MODULE_POWER_MODULE_STATUS_Count                                    1
+#define GC_MODULE_POWER_MODULE_STATUS_FieldMask                       0x00000007
+#define GC_MODULE_POWER_MODULE_STATUS_ReadMask                        0x00000007
+#define GC_MODULE_POWER_MODULE_STATUS_WriteMask                       0x00000000
+#define GC_MODULE_POWER_MODULE_STATUS_ResetValue                      0x00000000
+
+/* Module level clock gating is ON for FE. */
+#define GC_MODULE_POWER_MODULE_STATUS_MODULE_CLOCK_GATED_FE                0 : 0
+#define GC_MODULE_POWER_MODULE_STATUS_MODULE_CLOCK_GATED_FE_End                0
+#define GC_MODULE_POWER_MODULE_STATUS_MODULE_CLOCK_GATED_FE_Start              0
+#define GC_MODULE_POWER_MODULE_STATUS_MODULE_CLOCK_GATED_FE_Type             U01
+
+/* Module level clock gating is ON for DE. */
+#define GC_MODULE_POWER_MODULE_STATUS_MODULE_CLOCK_GATED_DE                1 : 1
+#define GC_MODULE_POWER_MODULE_STATUS_MODULE_CLOCK_GATED_DE_End                1
+#define GC_MODULE_POWER_MODULE_STATUS_MODULE_CLOCK_GATED_DE_Start              1
+#define GC_MODULE_POWER_MODULE_STATUS_MODULE_CLOCK_GATED_DE_Type             U01
+
+/* Module level clock gating is ON for PE. */
+#define GC_MODULE_POWER_MODULE_STATUS_MODULE_CLOCK_GATED_PE                2 : 2
+#define GC_MODULE_POWER_MODULE_STATUS_MODULE_CLOCK_GATED_PE_End                2
+#define GC_MODULE_POWER_MODULE_STATUS_MODULE_CLOCK_GATED_PE_Start              2
+#define GC_MODULE_POWER_MODULE_STATUS_MODULE_CLOCK_GATED_PE_Type             U01
+
+/*******************************************************************************
+** State gcregSrcAddress
+*/
+
+/* 32-bit aligned base address of the source surface. */
+
+#define gcregSrcAddressRegAddrs                                           0x0480
+#define GCREG_SRC_ADDRESS_MSB                                                 15
+#define GCREG_SRC_ADDRESS_LSB                                                  0
+#define GCREG_SRC_ADDRESS_BLK                                                  0
+#define GCREG_SRC_ADDRESS_Count                                                1
+#define GCREG_SRC_ADDRESS_FieldMask                                   0xFFFFFFFF
+#define GCREG_SRC_ADDRESS_ReadMask                                    0xFFFFFFFC
+#define GCREG_SRC_ADDRESS_WriteMask                                   0xFFFFFFFC
+#define GCREG_SRC_ADDRESS_ResetValue                                  0x00000000
+
+#define GCREG_SRC_ADDRESS_ADDRESS                                         31 : 0
+#define GCREG_SRC_ADDRESS_ADDRESS_End                                         30
+#define GCREG_SRC_ADDRESS_ADDRESS_Start                                        0
+#define GCREG_SRC_ADDRESS_ADDRESS_Type                                       U31
+
+/*******************************************************************************
+** State gcregSrcStride
+*/
+
+/* Stride of the source surface in bytes. To calculate the stride multiply
+** the surface width in pixels (8-pixel aligned) by the number of bytes per
+** pixel.
+*/
+
+#define gcregSrcStrideRegAddrs                                            0x0481
+#define GCREG_SRC_STRIDE_MSB                                                  15
+#define GCREG_SRC_STRIDE_LSB                                                   0
+#define GCREG_SRC_STRIDE_BLK                                                   0
+#define GCREG_SRC_STRIDE_Count                                                 1
+#define GCREG_SRC_STRIDE_FieldMask                                    0x0003FFFF
+#define GCREG_SRC_STRIDE_ReadMask                                     0x0003FFFC
+#define GCREG_SRC_STRIDE_WriteMask                                    0x0003FFFC
+#define GCREG_SRC_STRIDE_ResetValue                                   0x00000000
+
+#define GCREG_SRC_STRIDE_STRIDE                                           17 : 0
+#define GCREG_SRC_STRIDE_STRIDE_End                                           17
+#define GCREG_SRC_STRIDE_STRIDE_Start                                          0
+#define GCREG_SRC_STRIDE_STRIDE_Type                                         U18
+
+/*******************************************************************************
+** State gcregSrcRotationConfig
+*/
+
+/* 90 degree rotation configuration for the source surface. Width field
+** specifies the width of the surface in pixels.
+*/
+
+#define gcregSrcRotationConfigRegAddrs                                    0x0482
+#define GCREG_SRC_ROTATION_CONFIG_MSB                                         15
+#define GCREG_SRC_ROTATION_CONFIG_LSB                                          0
+#define GCREG_SRC_ROTATION_CONFIG_BLK                                          0
+#define GCREG_SRC_ROTATION_CONFIG_Count                                        1
+#define GCREG_SRC_ROTATION_CONFIG_FieldMask                           0x0001FFFF
+#define GCREG_SRC_ROTATION_CONFIG_ReadMask                            0x0001FFFF
+#define GCREG_SRC_ROTATION_CONFIG_WriteMask                           0x0001FFFF
+#define GCREG_SRC_ROTATION_CONFIG_ResetValue                          0x00000000
+
+#define GCREG_SRC_ROTATION_CONFIG_WIDTH                                   15 : 0
+#define GCREG_SRC_ROTATION_CONFIG_WIDTH_End                                   15
+#define GCREG_SRC_ROTATION_CONFIG_WIDTH_Start                                  0
+#define GCREG_SRC_ROTATION_CONFIG_WIDTH_Type                                 U16
+
+#define GCREG_SRC_ROTATION_CONFIG_ROTATION                               16 : 16
+#define GCREG_SRC_ROTATION_CONFIG_ROTATION_End                                16
+#define GCREG_SRC_ROTATION_CONFIG_ROTATION_Start                              16
+#define GCREG_SRC_ROTATION_CONFIG_ROTATION_Type                              U01
+#define   GCREG_SRC_ROTATION_CONFIG_ROTATION_DISABLE                         0x0
+#define   GCREG_SRC_ROTATION_CONFIG_ROTATION_ENABLE                          0x1
+
+struct gcregsrcrotationconfig {
+	/* gcregSrcRotationConfigRegAddrs:GCREG_SRC_ROTATION_CONFIG_WIDTH */
+	unsigned int surf_width:16;
+
+	/* gcregSrcRotationConfigRegAddrs:GCREG_SRC_ROTATION_CONFIG_ROTATION */
+	unsigned int enable:1;
+
+	/* gcregSrcRotationConfigRegAddrs:reserved */
+	unsigned int _reserved_17_31:15;
+};
+
+/*******************************************************************************
+** State gcregSrcConfig
+*/
+
+/* Source surface configuration register. */
+
+#define gcregSrcConfigRegAddrs                                            0x0483
+#define GCREG_SRC_CONFIG_MSB                                                  15
+#define GCREG_SRC_CONFIG_LSB                                                   0
+#define GCREG_SRC_CONFIG_BLK                                                   0
+#define GCREG_SRC_CONFIG_Count                                                 1
+#define GCREG_SRC_CONFIG_FieldMask                                    0xFF31B1FF
+#define GCREG_SRC_CONFIG_ReadMask                                     0xFF31B1FF
+#define GCREG_SRC_CONFIG_WriteMask                                    0xFF31B1FF
+#define GCREG_SRC_CONFIG_ResetValue                                   0x00000000
+
+/* Control source endianess. */
+#define GCREG_SRC_CONFIG_ENDIAN_CONTROL                                  31 : 30
+#define GCREG_SRC_CONFIG_ENDIAN_CONTROL_End                                   31
+#define GCREG_SRC_CONFIG_ENDIAN_CONTROL_Start                                 30
+#define GCREG_SRC_CONFIG_ENDIAN_CONTROL_Type                                 U02
+#define   GCREG_SRC_CONFIG_ENDIAN_CONTROL_NO_SWAP                            0x0
+#define   GCREG_SRC_CONFIG_ENDIAN_CONTROL_SWAP_WORD                          0x1
+#define   GCREG_SRC_CONFIG_ENDIAN_CONTROL_SWAP_DWORD                         0x2
+
+/* Disable 420 L2 cache  NOTE: the field is valid for chips with 420 L2 cache **
+** defined.                                                                   */
+#define GCREG_SRC_CONFIG_DISABLE420_L2_CACHE                             29 : 29
+#define GCREG_SRC_CONFIG_DISABLE420_L2_CACHE_End                              29
+#define GCREG_SRC_CONFIG_DISABLE420_L2_CACHE_Start                            29
+#define GCREG_SRC_CONFIG_DISABLE420_L2_CACHE_Type                            U01
+#define   GCREG_SRC_CONFIG_DISABLE420_L2_CACHE_ENABLED                       0x0
+#define   GCREG_SRC_CONFIG_DISABLE420_L2_CACHE_DISABLED                      0x1
+
+/* Defines the pixel format of the source surface. */
+#define GCREG_SRC_CONFIG_SOURCE_FORMAT                                   28 : 24
+#define GCREG_SRC_CONFIG_SOURCE_FORMAT_End                                    28
+#define GCREG_SRC_CONFIG_SOURCE_FORMAT_Start                                  24
+#define GCREG_SRC_CONFIG_SOURCE_FORMAT_Type                                  U05
+#define   GCREG_SRC_CONFIG_SOURCE_FORMAT_X4R4G4B4                           0x00
+#define   GCREG_SRC_CONFIG_SOURCE_FORMAT_A4R4G4B4                           0x01
+#define   GCREG_SRC_CONFIG_SOURCE_FORMAT_X1R5G5B5                           0x02
+#define   GCREG_SRC_CONFIG_SOURCE_FORMAT_A1R5G5B5                           0x03
+#define   GCREG_SRC_CONFIG_SOURCE_FORMAT_R5G6B5                             0x04
+#define   GCREG_SRC_CONFIG_SOURCE_FORMAT_X8R8G8B8                           0x05
+#define   GCREG_SRC_CONFIG_SOURCE_FORMAT_A8R8G8B8                           0x06
+#define   GCREG_SRC_CONFIG_SOURCE_FORMAT_YUY2                               0x07
+#define   GCREG_SRC_CONFIG_SOURCE_FORMAT_UYVY                               0x08
+#define   GCREG_SRC_CONFIG_SOURCE_FORMAT_INDEX8                             0x09
+#define   GCREG_SRC_CONFIG_SOURCE_FORMAT_MONOCHROME                         0x0A
+#define   GCREG_SRC_CONFIG_SOURCE_FORMAT_YV12                               0x0F
+#define   GCREG_SRC_CONFIG_SOURCE_FORMAT_A8                                 0x10
+#define   GCREG_SRC_CONFIG_SOURCE_FORMAT_NV12                               0x11
+#define   GCREG_SRC_CONFIG_SOURCE_FORMAT_NV16                               0x12
+#define   GCREG_SRC_CONFIG_SOURCE_FORMAT_RG16                               0x13
+
+/* Color channel swizzles. */
+#define GCREG_SRC_CONFIG_SWIZZLE                                         21 : 20
+#define GCREG_SRC_CONFIG_SWIZZLE_End                                          21
+#define GCREG_SRC_CONFIG_SWIZZLE_Start                                        20
+#define GCREG_SRC_CONFIG_SWIZZLE_Type                                        U02
+#define   GCREG_SRC_CONFIG_SWIZZLE_ARGB                                      0x0
+#define   GCREG_SRC_CONFIG_SWIZZLE_RGBA                                      0x1
+#define   GCREG_SRC_CONFIG_SWIZZLE_ABGR                                      0x2
+#define   GCREG_SRC_CONFIG_SWIZZLE_BGRA                                      0x3
+
+/* Mono expansion: if 0, transparency color will be 0, otherwise transparency **
+** color will be 1.                                                           */
+#define GCREG_SRC_CONFIG_MONO_TRANSPARENCY                               15 : 15
+#define GCREG_SRC_CONFIG_MONO_TRANSPARENCY_End                                15
+#define GCREG_SRC_CONFIG_MONO_TRANSPARENCY_Start                              15
+#define GCREG_SRC_CONFIG_MONO_TRANSPARENCY_Type                              U01
+#define   GCREG_SRC_CONFIG_MONO_TRANSPARENCY_BACKGROUND                      0x0
+#define   GCREG_SRC_CONFIG_MONO_TRANSPARENCY_FOREGROUND                      0x1
+
+/* Mono expansion or masked blit: stream packing in pixels. Determines how    **
+** many horizontal pixels are there per each 32-bit chunk. For example, if    **
+** set to Packed8, each 32-bit chunk is 8-pixel wide, which also means that   **
+** it defines 4 vertical lines of pixels.                                     */
+#define GCREG_SRC_CONFIG_PACK                                            13 : 12
+#define GCREG_SRC_CONFIG_PACK_End                                             13
+#define GCREG_SRC_CONFIG_PACK_Start                                           12
+#define GCREG_SRC_CONFIG_PACK_Type                                           U02
+#define   GCREG_SRC_CONFIG_PACK_PACKED8                                      0x0
+#define   GCREG_SRC_CONFIG_PACK_PACKED16                                     0x1
+#define   GCREG_SRC_CONFIG_PACK_PACKED32                                     0x2
+#define   GCREG_SRC_CONFIG_PACK_UNPACKED                                     0x3
+
+/* Source data location: set to STREAM for mono expansion blits or masked     **
+** blits. For mono expansion blits the complete bitmap comes from the command **
+** stream. For masked blits the source data comes from the memory and the     **
+** mask from the command stream.                                              */
+#define GCREG_SRC_CONFIG_LOCATION                                          8 : 8
+#define GCREG_SRC_CONFIG_LOCATION_End                                          8
+#define GCREG_SRC_CONFIG_LOCATION_Start                                        8
+#define GCREG_SRC_CONFIG_LOCATION_Type                                       U01
+#define   GCREG_SRC_CONFIG_LOCATION_MEMORY                                   0x0
+#define   GCREG_SRC_CONFIG_LOCATION_STREAM                                   0x1
+
+/* Source linear/tiled address computation control. */
+#define GCREG_SRC_CONFIG_TILED                                             7 : 7
+#define GCREG_SRC_CONFIG_TILED_End                                             7
+#define GCREG_SRC_CONFIG_TILED_Start                                           7
+#define GCREG_SRC_CONFIG_TILED_Type                                          U01
+#define   GCREG_SRC_CONFIG_TILED_DISABLED                                    0x0
+#define   GCREG_SRC_CONFIG_TILED_ENABLED                                     0x1
+
+/* If set to ABSOLUTE, the source coordinates are treated as absolute         **
+** coordinates inside the source surface. If set to RELATIVE, the source      **
+** coordinates are treated as the offsets from the destination coordinates    **
+** with the source size equal to the size of the destination.                 */
+#define GCREG_SRC_CONFIG_SRC_RELATIVE                                      6 : 6
+#define GCREG_SRC_CONFIG_SRC_RELATIVE_End                                      6
+#define GCREG_SRC_CONFIG_SRC_RELATIVE_Start                                    6
+#define GCREG_SRC_CONFIG_SRC_RELATIVE_Type                                   U01
+#define   GCREG_SRC_CONFIG_SRC_RELATIVE_ABSOLUTE                             0x0
+#define   GCREG_SRC_CONFIG_SRC_RELATIVE_RELATIVE                             0x1
+
+struct gcregsrcconfig {
+	/* gcregSrcConfigRegAddrs:reserved */
+	unsigned int _reserved_0_5:6;
+
+	/* gcregSrcConfigRegAddrs:GCREG_SRC_CONFIG_SRC_RELATIVE */
+	unsigned int relative:1;
+
+	/* gcregSrcConfigRegAddrs:GCREG_SRC_CONFIG_TILED */
+	unsigned int tiled:1;
+
+	/* gcregSrcConfigRegAddrs:GCREG_SRC_CONFIG_LOCATION */
+	unsigned int stream:1;
+
+	/* gcregSrcConfigRegAddrs:reserved */
+	unsigned int _reserved_9_11:3;
+
+	/* gcregSrcConfigRegAddrs:GCREG_SRC_CONFIG_PACK */
+	unsigned int monopack:2;
+
+	/* gcregSrcConfigRegAddrs:reserved */
+	unsigned int _reserved_14:1;
+
+	/* gcregSrcConfigRegAddrs:GCREG_SRC_CONFIG_MONO_TRANSPARENCY */
+	unsigned int monotransp:1;
+
+	/* gcregSrcConfigRegAddrs:reserved */
+	unsigned int _reserved_16_19:4;
+
+	/* gcregSrcConfigRegAddrs:GCREG_SRC_CONFIG_SWIZZLE */
+	unsigned int swizzle:2;
+
+	/* gcregSrcConfigRegAddrs:reserved */
+	unsigned int _reserved_22_23:2;
+
+	/* gcregSrcConfigRegAddrs:GCREG_SRC_CONFIG_SOURCE_FORMAT */
+	unsigned int format:5;
+
+	/* gcregSrcConfigRegAddrs:GCREG_SRC_CONFIG_DISABLE420_L2_CACHE */
+	unsigned int disable420L2cache:1;
+
+	/* gcregSrcConfigRegAddrs:GCREG_SRC_CONFIG_ENDIAN_CONTROL */
+	unsigned int endian:2;
+};
+
+/*******************************************************************************
+** State gcregSrcOrigin
+*/
+
+/* Absolute or relative (see SRC_RELATIVE field of gcregSrcConfig register) X
+** and Y coordinates in pixels of the top left corner of the source rectangle
+** within the source surface.
+*/
+
+#define gcregSrcOriginRegAddrs                                            0x0484
+#define GCREG_SRC_ORIGIN_MSB                                                  15
+#define GCREG_SRC_ORIGIN_LSB                                                   0
+#define GCREG_SRC_ORIGIN_BLK                                                   0
+#define GCREG_SRC_ORIGIN_Count                                                 1
+#define GCREG_SRC_ORIGIN_FieldMask                                    0xFFFFFFFF
+#define GCREG_SRC_ORIGIN_ReadMask                                     0xFFFFFFFF
+#define GCREG_SRC_ORIGIN_WriteMask                                    0xFFFFFFFF
+#define GCREG_SRC_ORIGIN_ResetValue                                   0x00000000
+
+#define GCREG_SRC_ORIGIN_Y                                               31 : 16
+#define GCREG_SRC_ORIGIN_Y_End                                                31
+#define GCREG_SRC_ORIGIN_Y_Start                                              16
+#define GCREG_SRC_ORIGIN_Y_Type                                              U16
+
+#define GCREG_SRC_ORIGIN_X                                                15 : 0
+#define GCREG_SRC_ORIGIN_X_End                                                15
+#define GCREG_SRC_ORIGIN_X_Start                                               0
+#define GCREG_SRC_ORIGIN_X_Type                                              U16
+
+struct gcregsrcorigin {
+	/* gcregSrcOriginRegAddrs:GCREG_SRC_ORIGIN_X */
+	unsigned int x:16;
+
+	/* gcregSrcOriginRegAddrs:GCREG_SRC_ORIGIN_Y */
+	unsigned int y:16;
+};
+
+static const struct gcregsrcorigin gcregsrcorigin_min = {
+	/* gcregSrcOriginRegAddrs:GCREG_SRC_ORIGIN_X */
+	0,
+
+	/* gcregSrcOriginRegAddrs:GCREG_SRC_ORIGIN_Y */
+	0
+};
+
+/*******************************************************************************
+** State gcregSrcSize
+*/
+
+/* Width and height of the source rectangle in pixels. If the source is
+** relative (see SRC_RELATIVE field of gcregSrcConfig register) or a regular
+** bitblt is being performed without stretching, this register is ignored and
+** the source size is assumed to be the same as the destination.
+*/
+
+#define gcregSrcSizeRegAddrs                                              0x0485
+#define GCREG_SRC_SIZE_MSB                                                    15
+#define GCREG_SRC_SIZE_LSB                                                     0
+#define GCREG_SRC_SIZE_BLK                                                     0
+#define GCREG_SRC_SIZE_Count                                                   1
+#define GCREG_SRC_SIZE_FieldMask                                      0xFFFFFFFF
+#define GCREG_SRC_SIZE_ReadMask                                       0xFFFFFFFF
+#define GCREG_SRC_SIZE_WriteMask                                      0xFFFFFFFF
+#define GCREG_SRC_SIZE_ResetValue                                     0x00000000
+
+#define GCREG_SRC_SIZE_Y                                                 31 : 16
+#define GCREG_SRC_SIZE_Y_End                                                  31
+#define GCREG_SRC_SIZE_Y_Start                                                16
+#define GCREG_SRC_SIZE_Y_Type                                                U16
+
+#define GCREG_SRC_SIZE_X                                                  15 : 0
+#define GCREG_SRC_SIZE_X_End                                                  15
+#define GCREG_SRC_SIZE_X_Start                                                 0
+#define GCREG_SRC_SIZE_X_Type                                                U16
+
+struct gcregsrcsize {
+	/* gcregSrcOriginRegAddrs:GCREG_SRC_SIZE_X */
+	unsigned int width:16;
+
+	/* gcregSrcOriginRegAddrs:GCREG_SRC_SIZE_Y */
+	unsigned int height:16;
+};
+
+static const struct gcregsrcsize gcregsrcsize_max = {
+	/* gcregSrcOriginRegAddrs:GCREG_SRC_SIZE_X */
+	32767,
+
+	/* gcregSrcOriginRegAddrs:GCREG_SRC_SIZE_Y */
+	32767
+};
+
+/*******************************************************************************
+** State gcregSrcColorBg
+*/
+
+/* In mono expansion defines the source color if the mono pixel is 0. The color
+** must be set in A8R8G8B8 format. In color blits defines the source
+** transparency color and must be of the same format as the source surface.
+*/
+
+#define gcregSrcColorBgRegAddrs                                           0x0486
+#define GCREG_SRC_COLOR_BG_MSB                                                15
+#define GCREG_SRC_COLOR_BG_LSB                                                 0
+#define GCREG_SRC_COLOR_BG_BLK                                                 0
+#define GCREG_SRC_COLOR_BG_Count                                               1
+#define GCREG_SRC_COLOR_BG_FieldMask                                  0xFFFFFFFF
+#define GCREG_SRC_COLOR_BG_ReadMask                                   0xFFFFFFFF
+#define GCREG_SRC_COLOR_BG_WriteMask                                  0xFFFFFFFF
+#define GCREG_SRC_COLOR_BG_ResetValue                                 0x00000000
+
+#define GCREG_SRC_COLOR_BG_ALPHA                                         31 : 24
+#define GCREG_SRC_COLOR_BG_ALPHA_End                                          31
+#define GCREG_SRC_COLOR_BG_ALPHA_Start                                        24
+#define GCREG_SRC_COLOR_BG_ALPHA_Type                                        U08
+
+#define GCREG_SRC_COLOR_BG_RED                                           23 : 16
+#define GCREG_SRC_COLOR_BG_RED_End                                            23
+#define GCREG_SRC_COLOR_BG_RED_Start                                          16
+#define GCREG_SRC_COLOR_BG_RED_Type                                          U08
+
+#define GCREG_SRC_COLOR_BG_GREEN                                          15 : 8
+#define GCREG_SRC_COLOR_BG_GREEN_End                                          15
+#define GCREG_SRC_COLOR_BG_GREEN_Start                                         8
+#define GCREG_SRC_COLOR_BG_GREEN_Type                                        U08
+
+#define GCREG_SRC_COLOR_BG_BLUE                                            7 : 0
+#define GCREG_SRC_COLOR_BG_BLUE_End                                            7
+#define GCREG_SRC_COLOR_BG_BLUE_Start                                          0
+#define GCREG_SRC_COLOR_BG_BLUE_Type                                         U08
+
+/*******************************************************************************
+** State gcregSrcColorFg
+*/
+
+/* In mono expansion defines the source color if the mono pixel is 1. The color
+** must be set in A8R8G8B8.
+*/
+
+#define gcregSrcColorFgRegAddrs                                           0x0487
+#define GCREG_SRC_COLOR_FG_MSB                                                15
+#define GCREG_SRC_COLOR_FG_LSB                                                 0
+#define GCREG_SRC_COLOR_FG_BLK                                                 0
+#define GCREG_SRC_COLOR_FG_Count                                               1
+#define GCREG_SRC_COLOR_FG_FieldMask                                  0xFFFFFFFF
+#define GCREG_SRC_COLOR_FG_ReadMask                                   0xFFFFFFFF
+#define GCREG_SRC_COLOR_FG_WriteMask                                  0xFFFFFFFF
+#define GCREG_SRC_COLOR_FG_ResetValue                                 0x00000000
+
+#define GCREG_SRC_COLOR_FG_ALPHA                                         31 : 24
+#define GCREG_SRC_COLOR_FG_ALPHA_End                                          31
+#define GCREG_SRC_COLOR_FG_ALPHA_Start                                        24
+#define GCREG_SRC_COLOR_FG_ALPHA_Type                                        U08
+
+#define GCREG_SRC_COLOR_FG_RED                                           23 : 16
+#define GCREG_SRC_COLOR_FG_RED_End                                            23
+#define GCREG_SRC_COLOR_FG_RED_Start                                          16
+#define GCREG_SRC_COLOR_FG_RED_Type                                          U08
+
+#define GCREG_SRC_COLOR_FG_GREEN                                          15 : 8
+#define GCREG_SRC_COLOR_FG_GREEN_End                                          15
+#define GCREG_SRC_COLOR_FG_GREEN_Start                                         8
+#define GCREG_SRC_COLOR_FG_GREEN_Type                                        U08
+
+#define GCREG_SRC_COLOR_FG_BLUE                                            7 : 0
+#define GCREG_SRC_COLOR_FG_BLUE_End                                            7
+#define GCREG_SRC_COLOR_FG_BLUE_Start                                          0
+#define GCREG_SRC_COLOR_FG_BLUE_Type                                         U08
+
+/*******************************************************************************
+** State gcregStretchFactorLow
+*/
+
+#define gcregStretchFactorLowRegAddrs                                     0x0488
+#define GCREG_STRETCH_FACTOR_LOW_MSB                                          15
+#define GCREG_STRETCH_FACTOR_LOW_LSB                                           0
+#define GCREG_STRETCH_FACTOR_LOW_BLK                                           0
+#define GCREG_STRETCH_FACTOR_LOW_Count                                         1
+#define GCREG_STRETCH_FACTOR_LOW_FieldMask                            0x7FFFFFFF
+#define GCREG_STRETCH_FACTOR_LOW_ReadMask                             0x7FFFFFFF
+#define GCREG_STRETCH_FACTOR_LOW_WriteMask                            0x7FFFFFFF
+#define GCREG_STRETCH_FACTOR_LOW_ResetValue                           0x00000000
+
+/* Horizontal stretch factor in 15.16 fixed point format. The value is        **
+** calculated using the following formula: factor = ((srcWidth - 1) << 16) /  **
+** (dstWidth - 1). Stretch blit uses only the integer part of the value,      **
+** while Filter blit uses all 31 bits.                                        */
+#define GCREG_STRETCH_FACTOR_LOW_X                                        30 : 0
+#define GCREG_STRETCH_FACTOR_LOW_X_End                                        30
+#define GCREG_STRETCH_FACTOR_LOW_X_Start                                       0
+#define GCREG_STRETCH_FACTOR_LOW_X_Type                                      U31
+
+/*******************************************************************************
+** State gcregStretchFactorHigh
+*/
+
+#define gcregStretchFactorHighRegAddrs                                    0x0489
+#define GCREG_STRETCH_FACTOR_HIGH_MSB                                         15
+#define GCREG_STRETCH_FACTOR_HIGH_LSB                                          0
+#define GCREG_STRETCH_FACTOR_LOW_HIGH_BLK                                      0
+#define GCREG_STRETCH_FACTOR_HIGH_Count                                        1
+#define GCREG_STRETCH_FACTOR_HIGH_FieldMask                           0x7FFFFFFF
+#define GCREG_STRETCH_FACTOR_HIGH_ReadMask                            0x7FFFFFFF
+#define GCREG_STRETCH_FACTOR_HIGH_WriteMask                           0x7FFFFFFF
+#define GCREG_STRETCH_FACTOR_HIGH_ResetValue                          0x00000000
+
+/* Vertical stretch factor in 15.16 fixed point format. The value is          **
+** calculated using the following formula: factor = ((srcHeight - 1) << 16) / **
+** (dstHeight - 1). Stretch blit uses only the integer part of the value,     **
+** while Filter blit uses all 31 bits.                                        */
+#define GCREG_STRETCH_FACTOR_HIGH_Y                                       30 : 0
+#define GCREG_STRETCH_FACTOR_HIGH_Y_End                                       30
+#define GCREG_STRETCH_FACTOR_HIGH_Y_Start                                      0
+#define GCREG_STRETCH_FACTOR_HIGH_Y_Type                                     U31
+
+/*******************************************************************************
+** State gcregDestAddress
+*/
+
+/* 32-bit aligned base address of the destination surface. */
+
+#define gcregDestAddressRegAddrs                                          0x048A
+#define GCREG_DEST_ADDRESS_MSB                                                15
+#define GCREG_DEST_ADDRESS_LSB                                                 0
+#define GCREG_DEST_ADDRESS_BLK                                                 0
+#define GCREG_DEST_ADDRESS_Count                                               1
+#define GCREG_DEST_ADDRESS_FieldMask                                  0xFFFFFFFF
+#define GCREG_DEST_ADDRESS_ReadMask                                   0xFFFFFFFC
+#define GCREG_DEST_ADDRESS_WriteMask                                  0xFFFFFFFC
+#define GCREG_DEST_ADDRESS_ResetValue                                 0x00000000
+
+#define GCREG_DEST_ADDRESS_ADDRESS                                        31 : 0
+#define GCREG_DEST_ADDRESS_ADDRESS_End                                        30
+#define GCREG_DEST_ADDRESS_ADDRESS_Start                                       0
+#define GCREG_DEST_ADDRESS_ADDRESS_Type                                      U31
+
+/*******************************************************************************
+** State gcregDestStride
+*/
+
+/* Stride of the destination surface in bytes. To calculate the stride
+** multiply the surface width in pixels (8-pixel aligned) by the number of
+** bytes per pixel.
+*/
+
+#define gcregDestStrideRegAddrs                                           0x048B
+#define GCREG_DEST_STRIDE_MSB                                                 15
+#define GCREG_DEST_STRIDE_LSB                                                  0
+#define GCREG_DEST_STRIDE_BLK                                                  0
+#define GCREG_DEST_STRIDE_Count                                                1
+#define GCREG_DEST_STRIDE_FieldMask                                   0x0003FFFF
+#define GCREG_DEST_STRIDE_ReadMask                                    0x0003FFFC
+#define GCREG_DEST_STRIDE_WriteMask                                   0x0003FFFC
+#define GCREG_DEST_STRIDE_ResetValue                                  0x00000000
+
+#define GCREG_DEST_STRIDE_STRIDE                                          17 : 0
+#define GCREG_DEST_STRIDE_STRIDE_End                                          17
+#define GCREG_DEST_STRIDE_STRIDE_Start                                         0
+#define GCREG_DEST_STRIDE_STRIDE_Type                                        U18
+
+/*******************************************************************************
+** State gcregDestRotationConfig
+*/
+
+/* 90 degree rotation configuration for the destination surface. Width field
+** specifies the width of the surface in pixels.
+*/
+
+#define gcregDestRotationConfigRegAddrs                                   0x048C
+#define GCREG_DEST_ROTATION_CONFIG_MSB                                        15
+#define GCREG_DEST_ROTATION_CONFIG_LSB                                         0
+#define GCREG_DEST_ROTATION_CONFIG_BLK                                         0
+#define GCREG_DEST_ROTATION_CONFIG_Count                                       1
+#define GCREG_DEST_ROTATION_CONFIG_FieldMask                          0x0001FFFF
+#define GCREG_DEST_ROTATION_CONFIG_ReadMask                           0x0001FFFF
+#define GCREG_DEST_ROTATION_CONFIG_WriteMask                          0x0001FFFF
+#define GCREG_DEST_ROTATION_CONFIG_ResetValue                         0x00000000
+
+#define GCREG_DEST_ROTATION_CONFIG_WIDTH                                  15 : 0
+#define GCREG_DEST_ROTATION_CONFIG_WIDTH_End                                  15
+#define GCREG_DEST_ROTATION_CONFIG_WIDTH_Start                                 0
+#define GCREG_DEST_ROTATION_CONFIG_WIDTH_Type                                U16
+
+#define GCREG_DEST_ROTATION_CONFIG_ROTATION                              16 : 16
+#define GCREG_DEST_ROTATION_CONFIG_ROTATION_End                               16
+#define GCREG_DEST_ROTATION_CONFIG_ROTATION_Start                             16
+#define GCREG_DEST_ROTATION_CONFIG_ROTATION_Type                             U01
+#define   GCREG_DEST_ROTATION_CONFIG_ROTATION_DISABLE                        0x0
+#define   GCREG_DEST_ROTATION_CONFIG_ROTATION_ENABLE                         0x1
+
+struct gcregdstrotationconfig {
+	/* gcregDestRotationConfigRegAddrs:GCREG_DEST_ROTATION_CONFIG_WIDTH */
+	unsigned int surf_width:16;
+
+	/* gcregDestRotationConfigRegAddrs:GCREG_DEST_ROTATION_CONFIG_ROTATION*/
+	unsigned int enable:1;
+
+	/* gcregDestRotationConfigRegAddrs:reserved */
+	unsigned int _reserved_17_31:15;
+};
+
+/*******************************************************************************
+** State gcregDestConfig
+*/
+
+/* Destination surface configuration register. */
+
+#define gcregDestConfigRegAddrs                                           0x048D
+#define GCREG_DEST_CONFIG_MSB                                                 15
+#define GCREG_DEST_CONFIG_LSB                                                  0
+#define GCREG_DEST_CONFIG_BLK                                                  0
+#define GCREG_DEST_CONFIG_Count                                                1
+#define GCREG_DEST_CONFIG_FieldMask                                   0x0733F11F
+#define GCREG_DEST_CONFIG_ReadMask                                    0x0733F11F
+#define GCREG_DEST_CONFIG_WriteMask                                   0x0733F11F
+#define GCREG_DEST_CONFIG_ResetValue                                  0x00000000
+
+/* MinorTile. */
+#define GCREG_DEST_CONFIG_MINOR_TILED                                    26 : 26
+#define GCREG_DEST_CONFIG_MINOR_TILED_End                                     26
+#define GCREG_DEST_CONFIG_MINOR_TILED_Start                                   26
+#define GCREG_DEST_CONFIG_MINOR_TILED_Type                                   U01
+#define   GCREG_DEST_CONFIG_MINOR_TILED_DISABLED                             0x0
+#define   GCREG_DEST_CONFIG_MINOR_TILED_ENABLED                              0x1
+
+/* Performance fix for de. */
+#define GCREG_DEST_CONFIG_INTER_TILE_PER_FIX                             25 : 25
+#define GCREG_DEST_CONFIG_INTER_TILE_PER_FIX_End                              25
+#define GCREG_DEST_CONFIG_INTER_TILE_PER_FIX_Start                            25
+#define GCREG_DEST_CONFIG_INTER_TILE_PER_FIX_Type                            U01
+#define   GCREG_DEST_CONFIG_INTER_TILE_PER_FIX_DISABLED                      0x1
+#define   GCREG_DEST_CONFIG_INTER_TILE_PER_FIX_ENABLED                       0x0
+
+/* Control GDI Strecth Blit. */
+#define GCREG_DEST_CONFIG_GDI_STRE                                       24 : 24
+#define GCREG_DEST_CONFIG_GDI_STRE_End                                        24
+#define GCREG_DEST_CONFIG_GDI_STRE_Start                                      24
+#define GCREG_DEST_CONFIG_GDI_STRE_Type                                      U01
+#define   GCREG_DEST_CONFIG_GDI_STRE_DISABLED                                0x0
+#define   GCREG_DEST_CONFIG_GDI_STRE_ENABLED                                 0x1
+
+/* Control destination endianess. */
+#define GCREG_DEST_CONFIG_ENDIAN_CONTROL                                 21 : 20
+#define GCREG_DEST_CONFIG_ENDIAN_CONTROL_End                                  21
+#define GCREG_DEST_CONFIG_ENDIAN_CONTROL_Start                                20
+#define GCREG_DEST_CONFIG_ENDIAN_CONTROL_Type                                U02
+#define   GCREG_DEST_CONFIG_ENDIAN_CONTROL_NO_SWAP                           0x0
+#define   GCREG_DEST_CONFIG_ENDIAN_CONTROL_SWAP_WORD                         0x1
+#define   GCREG_DEST_CONFIG_ENDIAN_CONTROL_SWAP_DWORD                        0x2
+
+/* Color channel swizzles. */
+#define GCREG_DEST_CONFIG_SWIZZLE                                        17 : 16
+#define GCREG_DEST_CONFIG_SWIZZLE_End                                         17
+#define GCREG_DEST_CONFIG_SWIZZLE_Start                                       16
+#define GCREG_DEST_CONFIG_SWIZZLE_Type                                       U02
+#define   GCREG_DEST_CONFIG_SWIZZLE_ARGB                                     0x0
+#define   GCREG_DEST_CONFIG_SWIZZLE_RGBA                                     0x1
+#define   GCREG_DEST_CONFIG_SWIZZLE_ABGR                                     0x2
+#define   GCREG_DEST_CONFIG_SWIZZLE_BGRA                                     0x3
+
+/* Determines the type of primitive to be rendered. BIT_BLT_REVERSED and      **
+** INVALID_COMMAND values are defined for internal use and should not be      **
+** used.                                                                      */
+#define GCREG_DEST_CONFIG_COMMAND                                        15 : 12
+#define GCREG_DEST_CONFIG_COMMAND_End                                         15
+#define GCREG_DEST_CONFIG_COMMAND_Start                                       12
+#define GCREG_DEST_CONFIG_COMMAND_Type                                       U04
+#define   GCREG_DEST_CONFIG_COMMAND_CLEAR                                    0x0
+#define   GCREG_DEST_CONFIG_COMMAND_LINE                                     0x1
+#define   GCREG_DEST_CONFIG_COMMAND_BIT_BLT                                  0x2
+#define   GCREG_DEST_CONFIG_COMMAND_BIT_BLT_REVERSED                         0x3
+#define   GCREG_DEST_CONFIG_COMMAND_STRETCH_BLT                              0x4
+#define   GCREG_DEST_CONFIG_COMMAND_HOR_FILTER_BLT                           0x5
+#define   GCREG_DEST_CONFIG_COMMAND_VER_FILTER_BLT                           0x6
+#define   GCREG_DEST_CONFIG_COMMAND_ONE_PASS_FILTER_BLT                      0x7
+#define   GCREG_DEST_CONFIG_COMMAND_MULTI_SOURCE_BLT                         0x8
+
+/* Destination linear/tiled address computation control. Reserved field for   **
+** future expansion. */
+#define GCREG_DEST_CONFIG_TILED                                            8 : 8
+#define GCREG_DEST_CONFIG_TILED_End                                            8
+#define GCREG_DEST_CONFIG_TILED_Start                                          8
+#define GCREG_DEST_CONFIG_TILED_Type                                         U01
+#define   GCREG_DEST_CONFIG_TILED_DISABLED                                   0x0
+#define   GCREG_DEST_CONFIG_TILED_ENABLED                                    0x1
+
+/* Defines the pixel format of the destination surface. */
+#define GCREG_DEST_CONFIG_FORMAT                                           4 : 0
+#define GCREG_DEST_CONFIG_FORMAT_End                                           4
+#define GCREG_DEST_CONFIG_FORMAT_Start                                         0
+#define GCREG_DEST_CONFIG_FORMAT_Type                                        U05
+#define   GCREG_DEST_CONFIG_FORMAT_X4R4G4B4                                 0x00
+#define   GCREG_DEST_CONFIG_FORMAT_A4R4G4B4                                 0x01
+#define   GCREG_DEST_CONFIG_FORMAT_X1R5G5B5                                 0x02
+#define   GCREG_DEST_CONFIG_FORMAT_A1R5G5B5                                 0x03
+#define   GCREG_DEST_CONFIG_FORMAT_R5G6B5                                   0x04
+#define   GCREG_DEST_CONFIG_FORMAT_X8R8G8B8                                 0x05
+#define   GCREG_DEST_CONFIG_FORMAT_A8R8G8B8                                 0x06
+#define   GCREG_DEST_CONFIG_FORMAT_YUY2                                     0x07
+#define   GCREG_DEST_CONFIG_FORMAT_UYVY                                     0x08
+#define   GCREG_DEST_CONFIG_FORMAT_INDEX8                                   0x09
+#define   GCREG_DEST_CONFIG_FORMAT_MONOCHROME                               0x0A
+#define   GCREG_DEST_CONFIG_FORMAT_YV12                                     0x0F
+#define   GCREG_DEST_CONFIG_FORMAT_A8                                       0x10
+#define   GCREG_DEST_CONFIG_FORMAT_NV12                                     0x11
+#define   GCREG_DEST_CONFIG_FORMAT_NV16                                     0x12
+#define   GCREG_DEST_CONFIG_FORMAT_RG16                                     0x13
+
+struct gcregdstconfig {
+	/* gcregDestConfigRegAddrs:GCREG_DEST_CONFIG_FORMAT */
+	unsigned int format:5;
+
+	/* gcregDestConfigRegAddrs:reserved */
+	unsigned int _reserved_5_7:3;
+
+	/* gcregDestConfigRegAddrs:GCREG_DEST_CONFIG_TILED */
+	unsigned int tiled:1;
+
+	/* gcregDestConfigRegAddrs:reserved */
+	unsigned int _reserved_9_11:3;
+
+	/* gcregDestConfigRegAddrs:GCREG_DEST_CONFIG_COMMAND */
+	unsigned int command:4;
+
+	/* gcregDestConfigRegAddrs:GCREG_DEST_CONFIG_SWIZZLE */
+	unsigned int swizzle:2;
+
+	/* gcregDestConfigRegAddrs:reserved */
+	unsigned int _reserved_18_19:2;
+
+	/* gcregDestConfigRegAddrs:GCREG_DEST_CONFIG_ENDIAN_CONTROL */
+	unsigned int endian:2;
+
+	/* gcregDestConfigRegAddrs:reserved */
+	unsigned int _reserved_22_23:2;
+
+	/* gcregDestConfigRegAddrs:GCREG_DEST_CONFIG_GDI_STRE */
+	unsigned int gdi:1;
+
+	/* gcregDestConfigRegAddrs:GCREG_DEST_CONFIG_INTER_TILE_PER_FIX */
+	unsigned int inner_tile_fix:1;
+
+	/* gcregDestConfigRegAddrs:GCREG_DEST_CONFIG_MINOR_TILED */
+	unsigned int minor_tile:1;
+
+	/* gcregDestConfigRegAddrs:reserved */
+	unsigned int _reserved_27_31:5;
+};
+
+/*******************************************************************************
+** State gcregFilterKernel
+*/
+
+/* Filter blit coefficient table. The algorithm uses 5 bits of pixel
+** coordinate's fraction to index the kernel array, which makes it a 32-entry
+** array. Each entry consists of 9 kernel values. In practice we store only a
+** half of the table, because the other half is a mirror of the first,
+** therefore:
+**     rows_to_store    = 32 / 2 + 1 = 17
+**     values_to_store  = rows_to_store * 9 = 153
+**     even_value_count = (values_to_store + 1) & ~1 = 154
+**     dword_count      = even_value_count / 2 = 77
+*/
+
+#define gcregFilterKernelRegAddrs                                         0x0600
+#define GCREG_FILTER_KERNEL_MSB                                               15
+#define GCREG_FILTER_KERNEL_LSB                                                7
+#define GCREG_FILTER_KERNEL_BLK                                                7
+#define GCREG_FILTER_KERNEL_Count                                            128
+#define GCREG_FILTER_KERNEL_FieldMask                                 0xFFFFFFFF
+#define GCREG_FILTER_KERNEL_ReadMask                                  0xFFFFFFFF
+#define GCREG_FILTER_KERNEL_WriteMask                                 0xFFFFFFFF
+#define GCREG_FILTER_KERNEL_ResetValue                                0x00000000
+
+#define GCREG_FILTER_KERNEL_COEFFICIENT0                                  15 : 0
+#define GCREG_FILTER_KERNEL_COEFFICIENT0_End                                  15
+#define GCREG_FILTER_KERNEL_COEFFICIENT0_Start                                 0
+#define GCREG_FILTER_KERNEL_COEFFICIENT0_Type                                U16
+
+#define GCREG_FILTER_KERNEL_COEFFICIENT1                                 31 : 16
+#define GCREG_FILTER_KERNEL_COEFFICIENT1_End                                  31
+#define GCREG_FILTER_KERNEL_COEFFICIENT1_Start                                16
+#define GCREG_FILTER_KERNEL_COEFFICIENT1_Type                                U16
+
+struct gcregfilterkernelpair {
+	/* gcregFilterKernelRegAddrs:COEFFICIENT0 */
+	unsigned int coeff0:16;
+
+	/* gcregFilterKernelRegAddrs:COEFFICIENT1 */
+	unsigned int coeff1:16;
+};
+
+struct gcregfilterkernel {
+	struct gcregfilterkernelpair filter[77];
+};
+
+/*******************************************************************************
+** State gcregHoriFilterKernel
+*/
+
+/* One Pass filter Filter blit hori coefficient table. */
+
+#define gcregHoriFilterKernelRegAddrs                                     0x0A00
+#define GCREG_HORI_FILTER_KERNEL_MSB                                          15
+#define GCREG_HORI_FILTER_KERNEL_LSB                                           7
+#define GCREG_HORI_FILTER_KERNEL_BLK                                           7
+#define GCREG_HORI_FILTER_KERNEL_Count                                       128
+#define GCREG_HORI_FILTER_KERNEL_FieldMask                            0xFFFFFFFF
+#define GCREG_HORI_FILTER_KERNEL_ReadMask                             0xFFFFFFFF
+#define GCREG_HORI_FILTER_KERNEL_WriteMask                            0xFFFFFFFF
+#define GCREG_HORI_FILTER_KERNEL_ResetValue                           0x00000000
+
+#define GCREG_HORI_FILTER_KERNEL_COEFFICIENT0                             15 : 0
+#define GCREG_HORI_FILTER_KERNEL_COEFFICIENT0_End                             15
+#define GCREG_HORI_FILTER_KERNEL_COEFFICIENT0_Start                            0
+#define GCREG_HORI_FILTER_KERNEL_COEFFICIENT0_Type                           U16
+
+#define GCREG_HORI_FILTER_KERNEL_COEFFICIENT1                            31 : 16
+#define GCREG_HORI_FILTER_KERNEL_COEFFICIENT1_End                             31
+#define GCREG_HORI_FILTER_KERNEL_COEFFICIENT1_Start                           16
+#define GCREG_HORI_FILTER_KERNEL_COEFFICIENT1_Type                           U16
+
+/*******************************************************************************
+** State gcregVertiFilterKernel
+*/
+
+/* One Pass Filter blit vertical coefficient table. */
+
+#define gcregVertiFilterKernelRegAddrs                                    0x0A80
+#define GCREG_VERTI_FILTER_KERNEL_MSB                                         15
+#define GCREG_VERTI_FILTER_KERNEL_LSB                                          7
+#define GCREG_VERTI_FILTER_KERNEL_BLK                                          7
+#define GCREG_VERTI_FILTER_KERNEL_Count                                      128
+#define GCREG_VERTI_FILTER_KERNEL_FieldMask                           0xFFFFFFFF
+#define GCREG_VERTI_FILTER_KERNEL_ReadMask                            0xFFFFFFFF
+#define GCREG_VERTI_FILTER_KERNEL_WriteMask                           0xFFFFFFFF
+#define GCREG_VERTI_FILTER_KERNEL_ResetValue                          0x00000000
+
+#define GCREG_VERTI_FILTER_KERNEL_COEFFICIENT0                            15 : 0
+#define GCREG_VERTI_FILTER_KERNEL_COEFFICIENT0_End                            15
+#define GCREG_VERTI_FILTER_KERNEL_COEFFICIENT0_Start                           0
+#define GCREG_VERTI_FILTER_KERNEL_COEFFICIENT0_Type                          U16
+
+#define GCREG_VERTI_FILTER_KERNEL_COEFFICIENT1                           31 : 16
+#define GCREG_VERTI_FILTER_KERNEL_COEFFICIENT1_End                            31
+#define GCREG_VERTI_FILTER_KERNEL_COEFFICIENT1_Start                          16
+#define GCREG_VERTI_FILTER_KERNEL_COEFFICIENT1_Type                          U16
+
+/*******************************************************************************
+** State gcregVRConfig
+*/
+
+/* Video Rasterizer kick-off register. */
+
+#define gcregVRConfigRegAddrs                                             0x04A5
+#define GCREG_VR_CONFIG_MSB                                                   15
+#define GCREG_VR_CONFIG_LSB                                                    0
+#define GCREG_VR_CONFIG_BLK                                                    0
+#define GCREG_VR_CONFIG_Count                                                  1
+#define GCREG_VR_CONFIG_FieldMask                                     0x0000000B
+#define GCREG_VR_CONFIG_ReadMask                                      0x0000000B
+#define GCREG_VR_CONFIG_WriteMask                                     0x0000000B
+#define GCREG_VR_CONFIG_ResetValue                                    0x00000000
+
+/* Kick-off command. */
+#define GCREG_VR_CONFIG_START                                              1 : 0
+#define GCREG_VR_CONFIG_START_End                                              1
+#define GCREG_VR_CONFIG_START_Start                                            0
+#define GCREG_VR_CONFIG_START_Type                                           U02
+#define   GCREG_VR_CONFIG_START_HORIZONTAL_BLIT                              0x0
+#define   GCREG_VR_CONFIG_START_VERTICAL_BLIT                                0x1
+#define   GCREG_VR_CONFIG_START_ONE_PASS_BLIT                                0x2
+
+#define GCREG_VR_CONFIG_MASK_START                                         3 : 3
+#define GCREG_VR_CONFIG_MASK_START_End                                         3
+#define GCREG_VR_CONFIG_MASK_START_Start                                       3
+#define GCREG_VR_CONFIG_MASK_START_Type                                      U01
+#define   GCREG_VR_CONFIG_MASK_START_ENABLED                                 0x0
+#define   GCREG_VR_CONFIG_MASK_START_MASKED                                  0x1
+
+struct gcregvrconfig {
+	/* gcregVRConfigRegAddrs:START */
+	unsigned int start:2;
+
+	/* gcregVRConfigRegAddrs:reserved */
+	unsigned int _reserved_2:1;
+
+	/* gcregVRConfigRegAddrs:MASK_START */
+	unsigned int start_mask:1;
+
+	/* gcregVRConfigRegAddrs:reserved */
+	unsigned int _reserved_4_31:28;
+};
+
+static const struct gcregvrconfig gcregvrconfig_horizontal = {
+	/* gcregVRConfigRegAddrs:START */
+	GCREG_VR_CONFIG_START_HORIZONTAL_BLIT,
+
+	/* gcregVRConfigRegAddrs:reserved */
+	0,
+
+	/* gcregVRConfigRegAddrs:MASK_START */
+	GCREG_VR_CONFIG_MASK_START_ENABLED,
+
+	/* gcregVRConfigRegAddrs:reserved */
+	0
+};
+
+static const struct gcregvrconfig gcregvrconfig_vertical = {
+	/* gcregVRConfigRegAddrs:START */
+	GCREG_VR_CONFIG_START_VERTICAL_BLIT,
+
+	/* gcregVRConfigRegAddrs:reserved */
+	0,
+
+	/* gcregVRConfigRegAddrs:MASK_START */
+	GCREG_VR_CONFIG_MASK_START_ENABLED,
+
+	/* gcregVRConfigRegAddrs:reserved */
+	0
+};
+
+static const struct gcregvrconfig gcregvrconfig_onepass = {
+	/* gcregVRConfigRegAddrs:START */
+	GCREG_VR_CONFIG_START_ONE_PASS_BLIT,
+
+	/* gcregVRConfigRegAddrs:reserved */
+	0,
+
+	/* gcregVRConfigRegAddrs:MASK_START */
+	GCREG_VR_CONFIG_MASK_START_ENABLED,
+
+	/* gcregVRConfigRegAddrs:reserved */
+	0
+};
+
+/*******************************************************************************
+** State gcregVRSourceImageLow
+*/
+
+/* Bounding box of the source image. */
+
+#define gcregVRSourceImageLowRegAddrs                                     0x04A6
+#define GCREG_VR_SOURCE_IMAGE_LOW_Address                                0x01298
+#define GCREG_VR_SOURCE_IMAGE_LOW_MSB                                         15
+#define GCREG_VR_SOURCE_IMAGE_LOW_LSB                                          0
+#define GCREG_VR_SOURCE_IMAGE_LOW_BLK                                          0
+#define GCREG_VR_SOURCE_IMAGE_LOW_Count                                        1
+#define GCREG_VR_SOURCE_IMAGE_LOW_FieldMask                           0xFFFFFFFF
+#define GCREG_VR_SOURCE_IMAGE_LOW_ReadMask                            0xFFFFFFFF
+#define GCREG_VR_SOURCE_IMAGE_LOW_WriteMask                           0xFFFFFFFF
+#define GCREG_VR_SOURCE_IMAGE_LOW_ResetValue                          0x00000000
+
+#define GCREG_VR_SOURCE_IMAGE_LOW_LEFT                                    15 : 0
+#define GCREG_VR_SOURCE_IMAGE_LOW_LEFT_End                                    15
+#define GCREG_VR_SOURCE_IMAGE_LOW_LEFT_Start                                   0
+#define GCREG_VR_SOURCE_IMAGE_LOW_LEFT_Type                                  U16
+
+#define GCREG_VR_SOURCE_IMAGE_LOW_TOP                                    31 : 16
+#define GCREG_VR_SOURCE_IMAGE_LOW_TOP_End                                     31
+#define GCREG_VR_SOURCE_IMAGE_LOW_TOP_Start                                   16
+#define GCREG_VR_SOURCE_IMAGE_LOW_TOP_Type                                   U16
+
+struct gcregvrsourceimagelow {
+	/* gcregVRSourceImageLowRegAddrs:LEFT */
+	unsigned int left:16;
+
+	/* gcregVRSourceImageLowRegAddrs:TOP */
+	unsigned int top:16;
+};
+
+/*******************************************************************************
+** State gcregVRSourceImageHigh
+*/
+
+#define gcregVRSourceImageHighRegAddrs                                    0x04A7
+#define GCREG_VR_SOURCE_IMAGE_HIGH_MSB                                        15
+#define GCREG_VR_SOURCE_IMAGE_HIGH_LSB                                         0
+#define GCREG_VR_SOURCE_IMAGE_LOW_HIGH_BLK                                     0
+#define GCREG_VR_SOURCE_IMAGE_HIGH_Count                                       1
+#define GCREG_VR_SOURCE_IMAGE_HIGH_FieldMask                          0xFFFFFFFF
+#define GCREG_VR_SOURCE_IMAGE_HIGH_ReadMask                           0xFFFFFFFF
+#define GCREG_VR_SOURCE_IMAGE_HIGH_WriteMask                          0xFFFFFFFF
+#define GCREG_VR_SOURCE_IMAGE_HIGH_ResetValue                         0x00000000
+
+#define GCREG_VR_SOURCE_IMAGE_HIGH_RIGHT                                  15 : 0
+#define GCREG_VR_SOURCE_IMAGE_HIGH_RIGHT_End                                  15
+#define GCREG_VR_SOURCE_IMAGE_HIGH_RIGHT_Start                                 0
+#define GCREG_VR_SOURCE_IMAGE_HIGH_RIGHT_Type                                U16
+
+#define GCREG_VR_SOURCE_IMAGE_HIGH_BOTTOM                                31 : 16
+#define GCREG_VR_SOURCE_IMAGE_HIGH_BOTTOM_End                                 31
+#define GCREG_VR_SOURCE_IMAGE_HIGH_BOTTOM_Start                               16
+#define GCREG_VR_SOURCE_IMAGE_HIGH_BOTTOM_Type                               U16
+
+struct gcregvrsourceimagehigh {
+	/* gcregVRSourceImageHighRegAddrs:RIGHT */
+	unsigned int right:16;
+
+	/* gcregVRSourceImageHighRegAddrs:BOTTOM */
+	unsigned int bottom:16;
+};
+
+/*******************************************************************************
+** State gcregVRSourceOriginLow
+*/
+
+/* Fractional origin of the source window to be rendered within the source
+** image.
+*/
+
+#define gcregVRSourceOriginLowRegAddrs                                    0x04A8
+#define GCREG_VR_SOURCE_ORIGIN_LOW_MSB                                        15
+#define GCREG_VR_SOURCE_ORIGIN_LOW_LSB                                         0
+#define GCREG_VR_SOURCE_ORIGIN_LOW_BLK                                         0
+#define GCREG_VR_SOURCE_ORIGIN_LOW_Count                                       1
+#define GCREG_VR_SOURCE_ORIGIN_LOW_FieldMask                          0xFFFFFFFF
+#define GCREG_VR_SOURCE_ORIGIN_LOW_ReadMask                           0xFFFFFFFF
+#define GCREG_VR_SOURCE_ORIGIN_LOW_WriteMask                          0xFFFFFFFF
+#define GCREG_VR_SOURCE_ORIGIN_LOW_ResetValue                         0x00000000
+
+#define GCREG_VR_SOURCE_ORIGIN_LOW_X                                      31 : 0
+#define GCREG_VR_SOURCE_ORIGIN_LOW_X_End                                      31
+#define GCREG_VR_SOURCE_ORIGIN_LOW_X_Start                                     0
+#define GCREG_VR_SOURCE_ORIGIN_LOW_X_Type                                    U32
+
+/*******************************************************************************
+** State gcregVRSourceOriginHigh
+*/
+
+#define gcregVRSourceOriginHighRegAddrs                                   0x04A9
+#define GCREG_VR_SOURCE_ORIGIN_HIGH_MSB                                       15
+#define GCREG_VR_SOURCE_ORIGIN_HIGH_LSB                                        0
+#define GCREG_VR_SOURCE_ORIGIN_LOW_HIGH_BLK                                    0
+#define GCREG_VR_SOURCE_ORIGIN_HIGH_Count                                      1
+#define GCREG_VR_SOURCE_ORIGIN_HIGH_FieldMask                         0xFFFFFFFF
+#define GCREG_VR_SOURCE_ORIGIN_HIGH_ReadMask                          0xFFFFFFFF
+#define GCREG_VR_SOURCE_ORIGIN_HIGH_WriteMask                         0xFFFFFFFF
+#define GCREG_VR_SOURCE_ORIGIN_HIGH_ResetValue                        0x00000000
+
+#define GCREG_VR_SOURCE_ORIGIN_HIGH_Y                                     31 : 0
+#define GCREG_VR_SOURCE_ORIGIN_HIGH_Y_End                                     31
+#define GCREG_VR_SOURCE_ORIGIN_HIGH_Y_Start                                    0
+#define GCREG_VR_SOURCE_ORIGIN_HIGH_Y_Type                                   U32
+
+/*******************************************************************************
+** State gcregVRTargetWindowLow
+*/
+
+/* Bounding box of the destination window to be rendered within the
+** destination image.
+*/
+
+#define gcregVRTargetWindowLowRegAddrs                                    0x04AA
+#define GCREG_VR_TARGET_WINDOW_LOW_Address                               0x012A8
+#define GCREG_VR_TARGET_WINDOW_LOW_MSB                                        15
+#define GCREG_VR_TARGET_WINDOW_LOW_LSB                                         0
+#define GCREG_VR_TARGET_WINDOW_LOW_BLK                                         0
+#define GCREG_VR_TARGET_WINDOW_LOW_Count                                       1
+#define GCREG_VR_TARGET_WINDOW_LOW_FieldMask                          0xFFFFFFFF
+#define GCREG_VR_TARGET_WINDOW_LOW_ReadMask                           0xFFFFFFFF
+#define GCREG_VR_TARGET_WINDOW_LOW_WriteMask                          0xFFFFFFFF
+#define GCREG_VR_TARGET_WINDOW_LOW_ResetValue                         0x00000000
+
+#define GCREG_VR_TARGET_WINDOW_LOW_LEFT                                   15 : 0
+#define GCREG_VR_TARGET_WINDOW_LOW_LEFT_End                                   15
+#define GCREG_VR_TARGET_WINDOW_LOW_LEFT_Start                                  0
+#define GCREG_VR_TARGET_WINDOW_LOW_LEFT_Type                                 U16
+
+#define GCREG_VR_TARGET_WINDOW_LOW_TOP                                   31 : 16
+#define GCREG_VR_TARGET_WINDOW_LOW_TOP_End                                    31
+#define GCREG_VR_TARGET_WINDOW_LOW_TOP_Start                                  16
+#define GCREG_VR_TARGET_WINDOW_LOW_TOP_Type                                  U16
+
+struct gcregvrtargetwindowlow {
+	/* gcregVRTargetWindowLowRegAddrs:LEFT */
+	unsigned int left:16;
+
+	/* gcregVRTargetWindowLowRegAddrs:TOP */
+	unsigned int top:16;
+};
+
+/*******************************************************************************
+** State gcregVRTargetWindowHigh
+*/
+
+#define gcregVRTargetWindowHighRegAddrs                                   0x04AB
+#define GCREG_VR_TARGET_WINDOW_HIGH_MSB                                       15
+#define GCREG_VR_TARGET_WINDOW_HIGH_LSB                                        0
+#define GCREG_VR_TARGET_WINDOW_LOW_HIGH_BLK                                    0
+#define GCREG_VR_TARGET_WINDOW_HIGH_Count                                      1
+#define GCREG_VR_TARGET_WINDOW_HIGH_FieldMask                         0xFFFFFFFF
+#define GCREG_VR_TARGET_WINDOW_HIGH_ReadMask                          0xFFFFFFFF
+#define GCREG_VR_TARGET_WINDOW_HIGH_WriteMask                         0xFFFFFFFF
+#define GCREG_VR_TARGET_WINDOW_HIGH_ResetValue                        0x00000000
+
+#define GCREG_VR_TARGET_WINDOW_HIGH_RIGHT                                 15 : 0
+#define GCREG_VR_TARGET_WINDOW_HIGH_RIGHT_End                                 15
+#define GCREG_VR_TARGET_WINDOW_HIGH_RIGHT_Start                                0
+#define GCREG_VR_TARGET_WINDOW_HIGH_RIGHT_Type                               U16
+
+#define GCREG_VR_TARGET_WINDOW_HIGH_BOTTOM                               31 : 16
+#define GCREG_VR_TARGET_WINDOW_HIGH_BOTTOM_End                                31
+#define GCREG_VR_TARGET_WINDOW_HIGH_BOTTOM_Start                              16
+#define GCREG_VR_TARGET_WINDOW_HIGH_BOTTOM_Type                              U16
+
+struct gcregvrtargetwindowhigh {
+	/* gcregVRTargetWindowHighRegAddrs:LEFT */
+	unsigned int right:16;
+
+	/* gcregVRTargetWindowHighRegAddrs:TOP */
+	unsigned int bottom:16;
+};
+
+/*******************************************************************************
+** State gcregVRConfigEx
+*/
+
+/* Video Rasterizer configuration register. */
+
+#define gcregVRConfigExRegAddrs                                           0x04B9
+#define GCREG_VR_CONFIG_EX_Address                                       0x012E4
+#define GCREG_VR_CONFIG_EX_MSB                                                15
+#define GCREG_VR_CONFIG_EX_LSB                                                 0
+#define GCREG_VR_CONFIG_EX_BLK                                                 0
+#define GCREG_VR_CONFIG_EX_Count                                               1
+#define GCREG_VR_CONFIG_EX_FieldMask                                  0x000001FB
+#define GCREG_VR_CONFIG_EX_ReadMask                                   0x000001FB
+#define GCREG_VR_CONFIG_EX_WriteMask                                  0x000001FB
+#define GCREG_VR_CONFIG_EX_ResetValue                                 0x00000000
+
+/* Line width in pixels for vertical pass. */
+#define GCREG_VR_CONFIG_EX_VERTICAL_LINE_WIDTH                             1 : 0
+#define GCREG_VR_CONFIG_EX_VERTICAL_LINE_WIDTH_End                             1
+#define GCREG_VR_CONFIG_EX_VERTICAL_LINE_WIDTH_Start                           0
+#define GCREG_VR_CONFIG_EX_VERTICAL_LINE_WIDTH_Type                          U02
+#define   GCREG_VR_CONFIG_EX_VERTICAL_LINE_WIDTH_AUTO                        0x0
+#define   GCREG_VR_CONFIG_EX_VERTICAL_LINE_WIDTH_PIXELS16                    0x1
+#define   GCREG_VR_CONFIG_EX_VERTICAL_LINE_WIDTH_PIXELS32                    0x2
+
+#define GCREG_VR_CONFIG_EX_MASK_VERTICAL_LINE_WIDTH                        3 : 3
+#define GCREG_VR_CONFIG_EX_MASK_VERTICAL_LINE_WIDTH_End                        3
+#define GCREG_VR_CONFIG_EX_MASK_VERTICAL_LINE_WIDTH_Start                      3
+#define GCREG_VR_CONFIG_EX_MASK_VERTICAL_LINE_WIDTH_Type                     U01
+#define   GCREG_VR_CONFIG_EX_MASK_VERTICAL_LINE_WIDTH_ENABLED                0x0
+#define   GCREG_VR_CONFIG_EX_MASK_VERTICAL_LINE_WIDTH_MASKED                 0x1
+
+/* one pass filter tap. */
+#define GCREG_VR_CONFIG_EX_FILTER_TAP                                      7 : 4
+#define GCREG_VR_CONFIG_EX_FILTER_TAP_End                                      7
+#define GCREG_VR_CONFIG_EX_FILTER_TAP_Start                                    4
+#define GCREG_VR_CONFIG_EX_FILTER_TAP_Type                                   U04
+
+#define GCREG_VR_CONFIG_EX_MASK_FILTER_TAP                                 8 : 8
+#define GCREG_VR_CONFIG_EX_MASK_FILTER_TAP_End                                 8
+#define GCREG_VR_CONFIG_EX_MASK_FILTER_TAP_Start                               8
+#define GCREG_VR_CONFIG_EX_MASK_FILTER_TAP_Type                              U01
+#define   GCREG_VR_CONFIG_EX_MASK_FILTER_TAP_ENABLED                         0x0
+#define   GCREG_VR_CONFIG_EX_MASK_FILTER_TAP_MASKED                          0x1
+
+struct gcregvrconfigex {
+	/* gcregVRConfigExRegAddrs:VERTICAL_LINE_WIDTH */
+	unsigned int stripe:2;
+
+	/* gcregVRConfigExRegAddrs:reserved */
+	unsigned int _reserved_2:1;
+
+	/* gcregVRConfigExRegAddrs:MASK_VERTICAL_LINE_WIDTH */
+	unsigned int mask_stripe:1;
+
+	/* gcregVRConfigExRegAddrs:FILTER_TAP */
+	unsigned int kernelsize:4;
+
+	/* gcregVRConfigExRegAddrs:MASK_FILTER_TAP */
+	unsigned int mask_kernelsize:1;
+
+	/* gcregVRConfigExRegAddrs:reserved */
+	unsigned int _reserved_9_31:23;
+};
+
+/*******************************************************************************
+** State gcregBWConfig
+*/
+
+#define gcregBWConfigRegAddrs                                             0x04BC
+#define GCREG_BW_CONFIG_MSB                                                   15
+#define GCREG_BW_CONFIG_LSB                                                    0
+#define GCREG_BW_CONFIG_BLK                                                    0
+#define GCREG_BW_CONFIG_Count                                                  1
+#define GCREG_BW_CONFIG_FieldMask                                     0x00009999
+#define GCREG_BW_CONFIG_ReadMask                                      0x00009999
+#define GCREG_BW_CONFIG_WriteMask                                     0x00009999
+#define GCREG_BW_CONFIG_ResetValue                                    0x00000000
+
+/* One Pass Filter Block Config. */
+#define GCREG_BW_CONFIG_BLOCK_CONFIG                                       0 : 0
+#define GCREG_BW_CONFIG_BLOCK_CONFIG_End                                       0
+#define GCREG_BW_CONFIG_BLOCK_CONFIG_Start                                     0
+#define GCREG_BW_CONFIG_BLOCK_CONFIG_Type                                    U01
+#define   GCREG_BW_CONFIG_BLOCK_CONFIG_AUTO                                  0x0
+#define   GCREG_BW_CONFIG_BLOCK_CONFIG_CUSTOMIZE                             0x1
+
+#define GCREG_BW_CONFIG_MASK_BLOCK_CONFIG                                  3 : 3
+#define GCREG_BW_CONFIG_MASK_BLOCK_CONFIG_End                                  3
+#define GCREG_BW_CONFIG_MASK_BLOCK_CONFIG_Start                                3
+#define GCREG_BW_CONFIG_MASK_BLOCK_CONFIG_Type                               U01
+#define   GCREG_BW_CONFIG_MASK_BLOCK_CONFIG_ENABLED                          0x0
+#define   GCREG_BW_CONFIG_MASK_BLOCK_CONFIG_MASKED                           0x1
+
+/* block walk direction in one pass filter blit. */
+#define GCREG_BW_CONFIG_BLOCK_WALK_DIRECTION                               4 : 4
+#define GCREG_BW_CONFIG_BLOCK_WALK_DIRECTION_End                               4
+#define GCREG_BW_CONFIG_BLOCK_WALK_DIRECTION_Start                             4
+#define GCREG_BW_CONFIG_BLOCK_WALK_DIRECTION_Type                            U01
+#define   GCREG_BW_CONFIG_BLOCK_WALK_DIRECTION_RIGHT_BOTTOM                  0x0
+#define   GCREG_BW_CONFIG_BLOCK_WALK_DIRECTION_BOTTOM_RIGHT                  0x1
+
+#define GCREG_BW_CONFIG_MASK_BLOCK_WALK_DIRECTION                          7 : 7
+#define GCREG_BW_CONFIG_MASK_BLOCK_WALK_DIRECTION_End                          7
+#define GCREG_BW_CONFIG_MASK_BLOCK_WALK_DIRECTION_Start                        7
+#define GCREG_BW_CONFIG_MASK_BLOCK_WALK_DIRECTION_Type                       U01
+#define   GCREG_BW_CONFIG_MASK_BLOCK_WALK_DIRECTION_ENABLED                  0x0
+#define   GCREG_BW_CONFIG_MASK_BLOCK_WALK_DIRECTION_MASKED                   0x1
+
+/* block walk direction in one pass filter blit. */
+#define GCREG_BW_CONFIG_TILE_WALK_DIRECTION                                8 : 8
+#define GCREG_BW_CONFIG_TILE_WALK_DIRECTION_End                                8
+#define GCREG_BW_CONFIG_TILE_WALK_DIRECTION_Start                              8
+#define GCREG_BW_CONFIG_TILE_WALK_DIRECTION_Type                             U01
+#define   GCREG_BW_CONFIG_TILE_WALK_DIRECTION_RIGHT_BOTTOM                   0x0
+#define   GCREG_BW_CONFIG_TILE_WALK_DIRECTION_BOTTOM_RIGHT                   0x1
+
+#define GCREG_BW_CONFIG_MASK_TILE_WALK_DIRECTION                         11 : 11
+#define GCREG_BW_CONFIG_MASK_TILE_WALK_DIRECTION_End                          11
+#define GCREG_BW_CONFIG_MASK_TILE_WALK_DIRECTION_Start                        11
+#define GCREG_BW_CONFIG_MASK_TILE_WALK_DIRECTION_Type                        U01
+#define   GCREG_BW_CONFIG_MASK_TILE_WALK_DIRECTION_ENABLED                   0x0
+#define   GCREG_BW_CONFIG_MASK_TILE_WALK_DIRECTION_MASKED                    0x1
+
+/* block walk direction in one pass filter blit. */
+#define GCREG_BW_CONFIG_PIXEL_WALK_DIRECTION                             12 : 12
+#define GCREG_BW_CONFIG_PIXEL_WALK_DIRECTION_End                              12
+#define GCREG_BW_CONFIG_PIXEL_WALK_DIRECTION_Start                            12
+#define GCREG_BW_CONFIG_PIXEL_WALK_DIRECTION_Type                            U01
+#define   GCREG_BW_CONFIG_PIXEL_WALK_DIRECTION_RIGHT_BOTTOM                  0x0
+#define   GCREG_BW_CONFIG_PIXEL_WALK_DIRECTION_BOTTOM_RIGHT                  0x1
+
+#define GCREG_BW_CONFIG_MASK_PIXEL_WALK_DIRECTION                        15 : 15
+#define GCREG_BW_CONFIG_MASK_PIXEL_WALK_DIRECTION_End                         15
+#define GCREG_BW_CONFIG_MASK_PIXEL_WALK_DIRECTION_Start                       15
+#define GCREG_BW_CONFIG_MASK_PIXEL_WALK_DIRECTION_Type                       U01
+#define   GCREG_BW_CONFIG_MASK_PIXEL_WALK_DIRECTION_ENABLED                  0x0
+#define   GCREG_BW_CONFIG_MASK_PIXEL_WALK_DIRECTION_MASKED                   0x1
+
+/*******************************************************************************
+** State gcregBWBlockSize
+*/
+
+/* Walker Block size. */
+
+#define gcregBWBlockSizeRegAddrs                                          0x04BD
+#define GCREG_BW_BLOCK_SIZE_MSB                                               15
+#define GCREG_BW_BLOCK_SIZE_LSB                                                0
+#define GCREG_BW_BLOCK_SIZE_BLK                                                0
+#define GCREG_BW_BLOCK_SIZE_Count                                              1
+#define GCREG_BW_BLOCK_SIZE_FieldMask                                 0xFFFFFFFF
+#define GCREG_BW_BLOCK_SIZE_ReadMask                                  0xFFFFFFFF
+#define GCREG_BW_BLOCK_SIZE_WriteMask                                 0xFFFFFFFF
+#define GCREG_BW_BLOCK_SIZE_ResetValue                                0x00000000
+
+#define GCREG_BW_BLOCK_SIZE_WIDTH                                         15 : 0
+#define GCREG_BW_BLOCK_SIZE_WIDTH_End                                         15
+#define GCREG_BW_BLOCK_SIZE_WIDTH_Start                                        0
+#define GCREG_BW_BLOCK_SIZE_WIDTH_Type                                       U16
+
+#define GCREG_BW_BLOCK_SIZE_HEIGHT                                       31 : 16
+#define GCREG_BW_BLOCK_SIZE_HEIGHT_End                                        31
+#define GCREG_BW_BLOCK_SIZE_HEIGHT_Start                                      16
+#define GCREG_BW_BLOCK_SIZE_HEIGHT_Type                                      U16
+
+/*******************************************************************************
+** State gcregBWTileSize
+*/
+
+/* Walker tile size. */
+
+#define gcregBWTileSizeRegAddrs                                           0x04BE
+#define GCREG_BW_TILE_SIZE_MSB                                                15
+#define GCREG_BW_TILE_SIZE_LSB                                                 0
+#define GCREG_BW_TILE_SIZE_BLK                                                 0
+#define GCREG_BW_TILE_SIZE_Count                                               1
+#define GCREG_BW_TILE_SIZE_FieldMask                                  0xFFFFFFFF
+#define GCREG_BW_TILE_SIZE_ReadMask                                   0xFFFFFFFF
+#define GCREG_BW_TILE_SIZE_WriteMask                                  0xFFFFFFFF
+#define GCREG_BW_TILE_SIZE_ResetValue                                 0x00000000
+
+#define GCREG_BW_TILE_SIZE_WIDTH                                          15 : 0
+#define GCREG_BW_TILE_SIZE_WIDTH_End                                          15
+#define GCREG_BW_TILE_SIZE_WIDTH_Start                                         0
+#define GCREG_BW_TILE_SIZE_WIDTH_Type                                        U16
+
+#define GCREG_BW_TILE_SIZE_HEIGHT                                        31 : 16
+#define GCREG_BW_TILE_SIZE_HEIGHT_End                                         31
+#define GCREG_BW_TILE_SIZE_HEIGHT_Start                                       16
+#define GCREG_BW_TILE_SIZE_HEIGHT_Type                                       U16
+
+/*******************************************************************************
+** State gcregBWBlockMask
+*/
+
+/* Walker Block Mask. */
+
+#define gcregBWBlockMaskRegAddrs                                          0x04BF
+#define GCREG_BW_BLOCK_MASK_MSB                                               15
+#define GCREG_BW_BLOCK_MASK_LSB                                                0
+#define GCREG_BW_BLOCK_MASK_BLK                                                0
+#define GCREG_BW_BLOCK_MASK_Count                                              1
+#define GCREG_BW_BLOCK_MASK_FieldMask                                 0xFFFFFFFF
+#define GCREG_BW_BLOCK_MASK_ReadMask                                  0xFFFFFFFF
+#define GCREG_BW_BLOCK_MASK_WriteMask                                 0xFFFFFFFF
+#define GCREG_BW_BLOCK_MASK_ResetValue                                0x00000000
+
+#define GCREG_BW_BLOCK_MASK_HORIZONTAL                                    15 : 0
+#define GCREG_BW_BLOCK_MASK_HORIZONTAL_End                                    15
+#define GCREG_BW_BLOCK_MASK_HORIZONTAL_Start                                   0
+#define GCREG_BW_BLOCK_MASK_HORIZONTAL_Type                                  U16
+
+#define GCREG_BW_BLOCK_MASK_VERTICAL                                     31 : 16
+#define GCREG_BW_BLOCK_MASK_VERTICAL_End                                      31
+#define GCREG_BW_BLOCK_MASK_VERTICAL_Start                                    16
+#define GCREG_BW_BLOCK_MASK_VERTICAL_Type                                    U16
+
+/*******************************************************************************
+** State gcregIndexColorTable
+*/
+
+/* 256 color entries for the indexed color mode. Colors are assumed to be in
+** the destination format and no color conversion is done on the values.
+*/
+
+#define gcregIndexColorTableRegAddrs                                      0x0700
+#define GCREG_INDEX_COLOR_TABLE_MSB                                           15
+#define GCREG_INDEX_COLOR_TABLE_LSB                                            8
+#define GCREG_INDEX_COLOR_TABLE_BLK                                            8
+#define GCREG_INDEX_COLOR_TABLE_Count                                        256
+#define GCREG_INDEX_COLOR_TABLE_FieldMask                             0xFFFFFFFF
+#define GCREG_INDEX_COLOR_TABLE_ReadMask                              0xFFFFFFFF
+#define GCREG_INDEX_COLOR_TABLE_WriteMask                             0xFFFFFFFF
+#define GCREG_INDEX_COLOR_TABLE_ResetValue                            0x00000000
+
+#define GCREG_INDEX_COLOR_TABLE_ALPHA                                    31 : 24
+#define GCREG_INDEX_COLOR_TABLE_ALPHA_End                                     31
+#define GCREG_INDEX_COLOR_TABLE_ALPHA_Start                                   24
+#define GCREG_INDEX_COLOR_TABLE_ALPHA_Type                                   U08
+
+#define GCREG_INDEX_COLOR_TABLE_RED                                      23 : 16
+#define GCREG_INDEX_COLOR_TABLE_RED_End                                       23
+#define GCREG_INDEX_COLOR_TABLE_RED_Start                                     16
+#define GCREG_INDEX_COLOR_TABLE_RED_Type                                     U08
+
+#define GCREG_INDEX_COLOR_TABLE_GREEN                                     15 : 8
+#define GCREG_INDEX_COLOR_TABLE_GREEN_End                                     15
+#define GCREG_INDEX_COLOR_TABLE_GREEN_Start                                    8
+#define GCREG_INDEX_COLOR_TABLE_GREEN_Type                                   U08
+
+#define GCREG_INDEX_COLOR_TABLE_BLUE                                       7 : 0
+#define GCREG_INDEX_COLOR_TABLE_BLUE_End                                       7
+#define GCREG_INDEX_COLOR_TABLE_BLUE_Start                                     0
+#define GCREG_INDEX_COLOR_TABLE_BLUE_Type                                    U08
+
+/*******************************************************************************
+** State gcregIndexColorTable32
+*/
+
+/* 256 color entries for the indexed color mode. Colors are assumed to be in
+** the A8R8G8B8 format and no color conversion is done on the values. This
+** register is used only with chips with PE20 feature available.
+*/
+
+#define gcregIndexColorTable32RegAddrs                                    0x0D00
+#define GCREG_INDEX_COLOR_TABLE32_MSB                                         15
+#define GCREG_INDEX_COLOR_TABLE32_LSB                                          8
+#define GCREG_INDEX_COLOR_TABLE32_BLK                                          8
+#define GCREG_INDEX_COLOR_TABLE32_Count                                      256
+#define GCREG_INDEX_COLOR_TABLE32_FieldMask                           0xFFFFFFFF
+#define GCREG_INDEX_COLOR_TABLE32_ReadMask                            0xFFFFFFFF
+#define GCREG_INDEX_COLOR_TABLE32_WriteMask                           0xFFFFFFFF
+#define GCREG_INDEX_COLOR_TABLE32_ResetValue                          0x00000000
+
+#define GCREG_INDEX_COLOR_TABLE32_ALPHA                                  31 : 24
+#define GCREG_INDEX_COLOR_TABLE32_ALPHA_End                                   31
+#define GCREG_INDEX_COLOR_TABLE32_ALPHA_Start                                 24
+#define GCREG_INDEX_COLOR_TABLE32_ALPHA_Type                                 U08
+
+#define GCREG_INDEX_COLOR_TABLE32_RED                                    23 : 16
+#define GCREG_INDEX_COLOR_TABLE32_RED_End                                     23
+#define GCREG_INDEX_COLOR_TABLE32_RED_Start                                   16
+#define GCREG_INDEX_COLOR_TABLE32_RED_Type                                   U08
+
+#define GCREG_INDEX_COLOR_TABLE32_GREEN                                   15 : 8
+#define GCREG_INDEX_COLOR_TABLE32_GREEN_End                                   15
+#define GCREG_INDEX_COLOR_TABLE32_GREEN_Start                                  8
+#define GCREG_INDEX_COLOR_TABLE32_GREEN_Type                                 U08
+
+#define GCREG_INDEX_COLOR_TABLE32_BLUE                                     7 : 0
+#define GCREG_INDEX_COLOR_TABLE32_BLUE_End                                     7
+#define GCREG_INDEX_COLOR_TABLE32_BLUE_Start                                   0
+#define GCREG_INDEX_COLOR_TABLE32_BLUE_Type                                  U08
+
+/*******************************************************************************
+** State gcregRop
+*/
+
+/* Raster operation foreground and background codes. Even though ROP is not
+** used in CLEAR, HOR_FILTER_BLT, VER_FILTER_BLT and alpha-eanbled BIT_BLTs,
+** ROP code still has to be programmed, because the engine makes the decision
+** whether source, destination and pattern are involved in the current
+** operation and the correct decision is essential for the engine to complete
+** the operation as expected.
+*/
+
+#define gcregRopRegAddrs                                                  0x0497
+#define GCREG_ROP_MSB                                                         15
+#define GCREG_ROP_LSB                                                          0
+#define GCREG_ROP_BLK                                                          0
+#define GCREG_ROP_Count                                                        1
+#define GCREG_ROP_FieldMask                                           0x0030FFFF
+#define GCREG_ROP_ReadMask                                            0x0030FFFF
+#define GCREG_ROP_WriteMask                                           0x0030FFFF
+#define GCREG_ROP_ResetValue                                          0x00000000
+
+/* ROP type: ROP2, ROP3 or ROP4 */
+#define GCREG_ROP_TYPE                                                   21 : 20
+#define GCREG_ROP_TYPE_End                                                    21
+#define GCREG_ROP_TYPE_Start                                                  20
+#define GCREG_ROP_TYPE_Type                                                  U02
+#define   GCREG_ROP_TYPE_ROP2_PATTERN                                        0x0
+#define   GCREG_ROP_TYPE_ROP2_SOURCE                                         0x1
+#define   GCREG_ROP_TYPE_ROP3                                                0x2
+#define   GCREG_ROP_TYPE_ROP4                                                0x3
+
+/* Background ROP code is used for transparent pixels. */
+#define GCREG_ROP_ROP_BG                                                  15 : 8
+#define GCREG_ROP_ROP_BG_End                                                  15
+#define GCREG_ROP_ROP_BG_Start                                                 8
+#define GCREG_ROP_ROP_BG_Type                                                U08
+
+/* Background ROP code is used for opaque pixels. */
+#define GCREG_ROP_ROP_FG                                                   7 : 0
+#define GCREG_ROP_ROP_FG_End                                                   7
+#define GCREG_ROP_ROP_FG_Start                                                 0
+#define GCREG_ROP_ROP_FG_Type                                                U08
+
+struct gcregrop {
+	/* gcregRopRegAddrs:ROP_FG */
+	unsigned int fg:8;
+
+	/* gcregRopRegAddrs:ROP_BG */
+	unsigned int bg:8;
+
+	/* gcregRopRegAddrs:reserved */
+	unsigned int _reserved_16_19:4;
+
+	/* gcregRopRegAddrs:ROP_TYPE */
+	unsigned int type:2;
+
+	/* gcregRopRegAddrs:reserved */
+	unsigned int _reserved_22_31:10;
+};
+
+/*******************************************************************************
+** State gcregClipTopLeft
+*/
+
+/* Top left corner of the clipping rectangle defined in pixels. Clipping is
+** always on and everything beyond the clipping rectangle will be clipped
+** out. Clipping is not used with filter blits.
+*/
+
+#define gcregClipTopLeftRegAddrs                                          0x0498
+#define GCREG_CLIP_TOP_LEFT_MSB                                               15
+#define GCREG_CLIP_TOP_LEFT_LSB                                                0
+#define GCREG_CLIP_TOP_LEFT_BLK                                                0
+#define GCREG_CLIP_TOP_LEFT_Count                                              1
+#define GCREG_CLIP_TOP_LEFT_FieldMask                                 0x7FFF7FFF
+#define GCREG_CLIP_TOP_LEFT_ReadMask                                  0x7FFF7FFF
+#define GCREG_CLIP_TOP_LEFT_WriteMask                                 0x7FFF7FFF
+#define GCREG_CLIP_TOP_LEFT_ResetValue                                0x00000000
+
+#define GCREG_CLIP_TOP_LEFT_Y                                            30 : 16
+#define GCREG_CLIP_TOP_LEFT_Y_End                                             30
+#define GCREG_CLIP_TOP_LEFT_Y_Start                                           16
+#define GCREG_CLIP_TOP_LEFT_Y_Type                                           U15
+
+#define GCREG_CLIP_TOP_LEFT_X                                             14 : 0
+#define GCREG_CLIP_TOP_LEFT_X_End                                             14
+#define GCREG_CLIP_TOP_LEFT_X_Start                                            0
+#define GCREG_CLIP_TOP_LEFT_X_Type                                           U15
+
+struct gcregcliplt {
+	/* gcregClipTopLeftRegAddrs:X */
+	unsigned int left:15;
+
+	/* gcregClipTopLeftRegAddrs:reserved */
+	unsigned int _reserved_15:1;
+
+	/* gcregClipTopLeftRegAddrs:Y */
+	unsigned int top:15;
+
+	/* gcregClipTopLeftRegAddrs:reserved */
+	unsigned int _reserved_31:1;
+};
+
+/*******************************************************************************
+** State gcregClipBottomRight
+*/
+
+/* Bottom right corner of the clipping rectangle defined in pixels. Clipping
+** is always on and everything beyond the clipping rectangle will be clipped
+** out. Clipping is not used with filter blits.
+*/
+
+#define gcregClipBottomRightRegAddrs                                      0x0499
+#define GCREG_CLIP_BOTTOM_RIGHT_MSB                                           15
+#define GCREG_CLIP_BOTTOM_RIGHT_LSB                                            0
+#define GCREG_CLIP_BOTTOM_RIGHT_BLK                                            0
+#define GCREG_CLIP_BOTTOM_RIGHT_Count                                          1
+#define GCREG_CLIP_BOTTOM_RIGHT_FieldMask                             0x7FFF7FFF
+#define GCREG_CLIP_BOTTOM_RIGHT_ReadMask                              0x7FFF7FFF
+#define GCREG_CLIP_BOTTOM_RIGHT_WriteMask                             0x7FFF7FFF
+#define GCREG_CLIP_BOTTOM_RIGHT_ResetValue                            0x00000000
+
+#define GCREG_CLIP_BOTTOM_RIGHT_Y                                        30 : 16
+#define GCREG_CLIP_BOTTOM_RIGHT_Y_End                                         30
+#define GCREG_CLIP_BOTTOM_RIGHT_Y_Start                                       16
+#define GCREG_CLIP_BOTTOM_RIGHT_Y_Type                                       U15
+
+#define GCREG_CLIP_BOTTOM_RIGHT_X                                         14 : 0
+#define GCREG_CLIP_BOTTOM_RIGHT_X_End                                         14
+#define GCREG_CLIP_BOTTOM_RIGHT_X_Start                                        0
+#define GCREG_CLIP_BOTTOM_RIGHT_X_Type                                       U15
+
+struct gcregcliprb {
+	/* gcregClipBottomRightRegAddrs:X */
+	unsigned int right:15;
+
+	/* gcregClipBottomRightRegAddrs:reserved */
+	unsigned int _reserved_15:1;
+
+	/* gcregClipBottomRightRegAddrs:Y */
+	unsigned int bottom:15;
+
+	/* gcregClipBottomRightRegAddrs:reserved */
+	unsigned int _reserved_31:1;
+};
+
+/*******************************************************************************
+** State gcregConfig
+*/
+
+#define gcregConfigRegAddrs                                               0x049B
+#define GCREG_CONFIG_MSB                                                      15
+#define GCREG_CONFIG_LSB                                                       0
+#define GCREG_CONFIG_BLK                                                       0
+#define GCREG_CONFIG_Count                                                     1
+#define GCREG_CONFIG_FieldMask                                        0x00370031
+#define GCREG_CONFIG_ReadMask                                         0x00370031
+#define GCREG_CONFIG_WriteMask                                        0x00370031
+#define GCREG_CONFIG_ResetValue                                       0x00000000
+
+#define GCREG_CONFIG_MIRROR_BLT_MODE                                       5 : 4
+#define GCREG_CONFIG_MIRROR_BLT_MODE_End                                       5
+#define GCREG_CONFIG_MIRROR_BLT_MODE_Start                                     4
+#define GCREG_CONFIG_MIRROR_BLT_MODE_Type                                    U02
+#define   GCREG_CONFIG_MIRROR_BLT_MODE_NORMAL                                0x0
+#define   GCREG_CONFIG_MIRROR_BLT_MODE_HMIRROR                               0x1
+#define   GCREG_CONFIG_MIRROR_BLT_MODE_VMIRROR                               0x2
+#define   GCREG_CONFIG_MIRROR_BLT_MODE_FULL_MIRROR                           0x3
+
+#define GCREG_CONFIG_MIRROR_BLT_ENABLE                                     0 : 0
+#define GCREG_CONFIG_MIRROR_BLT_ENABLE_End                                     0
+#define GCREG_CONFIG_MIRROR_BLT_ENABLE_Start                                   0
+#define GCREG_CONFIG_MIRROR_BLT_ENABLE_Type                                  U01
+#define   GCREG_CONFIG_MIRROR_BLT_ENABLE_OFF                                 0x0
+#define   GCREG_CONFIG_MIRROR_BLT_ENABLE_ON                                  0x1
+
+/* Source select for the old walkers. */
+#define GCREG_CONFIG_SOURCE_SELECT                                       18 : 16
+#define GCREG_CONFIG_SOURCE_SELECT_End                                        18
+#define GCREG_CONFIG_SOURCE_SELECT_Start                                      16
+#define GCREG_CONFIG_SOURCE_SELECT_Type                                      U03
+
+/* Destination select for the old walkers. */
+#define GCREG_CONFIG_DESTINATION_SELECT                                  21 : 20
+#define GCREG_CONFIG_DESTINATION_SELECT_End                                   21
+#define GCREG_CONFIG_DESTINATION_SELECT_Start                                 20
+#define GCREG_CONFIG_DESTINATION_SELECT_Type                                 U02
+
+/*******************************************************************************
+** State gcregSrcOriginFraction
+*/
+
+/* Fraction for the source origin. Together with values in gcregSrcOrigin
+** these values form signed 16.16 fixed point origin for the source
+** rectangle. Fractions are only used in filter blit in split frame mode.
+*/
+
+#define gcregSrcOriginFractionRegAddrs                                    0x049E
+#define GCREG_SRC_ORIGIN_FRACTION_MSB                                         15
+#define GCREG_SRC_ORIGIN_FRACTION_LSB                                          0
+#define GCREG_SRC_ORIGIN_FRACTION_BLK                                          0
+#define GCREG_SRC_ORIGIN_FRACTION_Count                                        1
+#define GCREG_SRC_ORIGIN_FRACTION_FieldMask                           0xFFFFFFFF
+#define GCREG_SRC_ORIGIN_FRACTION_ReadMask                            0xFFFFFFFF
+#define GCREG_SRC_ORIGIN_FRACTION_WriteMask                           0xFFFFFFFF
+#define GCREG_SRC_ORIGIN_FRACTION_ResetValue                          0x00000000
+
+#define GCREG_SRC_ORIGIN_FRACTION_Y                                      31 : 16
+#define GCREG_SRC_ORIGIN_FRACTION_Y_End                                       31
+#define GCREG_SRC_ORIGIN_FRACTION_Y_Start                                     16
+#define GCREG_SRC_ORIGIN_FRACTION_Y_Type                                     U16
+
+#define GCREG_SRC_ORIGIN_FRACTION_X                                       15 : 0
+#define GCREG_SRC_ORIGIN_FRACTION_X_End                                       15
+#define GCREG_SRC_ORIGIN_FRACTION_X_Start                                      0
+#define GCREG_SRC_ORIGIN_FRACTION_X_Type                                     U16
+
+/*******************************************************************************
+** State gcregAlphaControl
+*/
+
+#define gcregAlphaControlRegAddrs                                         0x049F
+#define GCREG_ALPHA_CONTROL_MSB                                               15
+#define GCREG_ALPHA_CONTROL_LSB                                                0
+#define GCREG_ALPHA_CONTROL_BLK                                                0
+#define GCREG_ALPHA_CONTROL_Count                                              1
+#define GCREG_ALPHA_CONTROL_FieldMask                                 0xFFFF0001
+#define GCREG_ALPHA_CONTROL_ReadMask                                  0xFFFF0001
+#define GCREG_ALPHA_CONTROL_WriteMask                                 0xFFFF0001
+#define GCREG_ALPHA_CONTROL_ResetValue                                0x00000000
+
+#define GCREG_ALPHA_CONTROL_ENABLE                                         0 : 0
+#define GCREG_ALPHA_CONTROL_ENABLE_End                                         0
+#define GCREG_ALPHA_CONTROL_ENABLE_Start                                       0
+#define GCREG_ALPHA_CONTROL_ENABLE_Type                                      U01
+#define   GCREG_ALPHA_CONTROL_ENABLE_OFF                                     0x0
+#define   GCREG_ALPHA_CONTROL_ENABLE_ON                                      0x1
+
+struct gcregalphacontrol {
+	/* gcregAlphaControlRegAddrs:GCREG_ALPHA_CONTROL_ENABLE */
+	unsigned int enable:1;
+
+	/* gcregAlphaControlRegAddrs:reserved */
+	unsigned int _reserved_1_31:31;
+};
+
+static const struct gcregalphacontrol gcregalpha_off = {
+	/* gcregAlphaControlRegAddrs:GCREG_ALPHA_CONTROL_ENABLE */
+	GCREG_ALPHA_CONTROL_ENABLE_OFF,
+
+	/* gcregAlphaControlRegAddrs:reserved */
+	0
+};
+
+static const struct gcregalphacontrol gcregalpha_on = {
+	/* gcregAlphaControlRegAddrs:GCREG_ALPHA_CONTROL_ENABLE */
+	GCREG_ALPHA_CONTROL_ENABLE_ON,
+
+	/* gcregAlphaControlRegAddrs:reserved */
+	0
+};
+
+/*******************************************************************************
+** State gcregAlphaModes
+*/
+
+#define gcregAlphaModesRegAddrs                                           0x04A0
+#define GCREG_ALPHA_MODES_MSB                                                 15
+#define GCREG_ALPHA_MODES_LSB                                                  0
+#define GCREG_ALPHA_MODES_BLK                                                  0
+#define GCREG_ALPHA_MODES_Count                                                1
+#define GCREG_ALPHA_MODES_FieldMask                                   0xFF113311
+#define GCREG_ALPHA_MODES_ReadMask                                    0xFF113311
+#define GCREG_ALPHA_MODES_WriteMask                                   0xFF113311
+#define GCREG_ALPHA_MODES_ResetValue                                  0x00000000
+
+#define GCREG_ALPHA_MODES_SRC_ALPHA_MODE                                   0 : 0
+#define GCREG_ALPHA_MODES_SRC_ALPHA_MODE_End                                   0
+#define GCREG_ALPHA_MODES_SRC_ALPHA_MODE_Start                                 0
+#define GCREG_ALPHA_MODES_SRC_ALPHA_MODE_Type                                U01
+#define   GCREG_ALPHA_MODES_SRC_ALPHA_MODE_NORMAL                            0x0
+#define   GCREG_ALPHA_MODES_SRC_ALPHA_MODE_INVERSED                          0x1
+
+#define GCREG_ALPHA_MODES_DST_ALPHA_MODE                                   4 : 4
+#define GCREG_ALPHA_MODES_DST_ALPHA_MODE_End                                   4
+#define GCREG_ALPHA_MODES_DST_ALPHA_MODE_Start                                 4
+#define GCREG_ALPHA_MODES_DST_ALPHA_MODE_Type                                U01
+#define   GCREG_ALPHA_MODES_DST_ALPHA_MODE_NORMAL                            0x0
+#define   GCREG_ALPHA_MODES_DST_ALPHA_MODE_INVERSED                          0x1
+
+#define GCREG_ALPHA_MODES_GLOBAL_SRC_ALPHA_MODE                            9 : 8
+#define GCREG_ALPHA_MODES_GLOBAL_SRC_ALPHA_MODE_End                            9
+#define GCREG_ALPHA_MODES_GLOBAL_SRC_ALPHA_MODE_Start                          8
+#define GCREG_ALPHA_MODES_GLOBAL_SRC_ALPHA_MODE_Type                         U02
+#define   GCREG_ALPHA_MODES_GLOBAL_SRC_ALPHA_MODE_NORMAL                     0x0
+#define   GCREG_ALPHA_MODES_GLOBAL_SRC_ALPHA_MODE_GLOBAL                     0x1
+#define   GCREG_ALPHA_MODES_GLOBAL_SRC_ALPHA_MODE_SCALED                     0x2
+
+#define GCREG_ALPHA_MODES_GLOBAL_DST_ALPHA_MODE                          13 : 12
+#define GCREG_ALPHA_MODES_GLOBAL_DST_ALPHA_MODE_End                           13
+#define GCREG_ALPHA_MODES_GLOBAL_DST_ALPHA_MODE_Start                         12
+#define GCREG_ALPHA_MODES_GLOBAL_DST_ALPHA_MODE_Type                         U02
+#define   GCREG_ALPHA_MODES_GLOBAL_DST_ALPHA_MODE_NORMAL                     0x0
+#define   GCREG_ALPHA_MODES_GLOBAL_DST_ALPHA_MODE_GLOBAL                     0x1
+#define   GCREG_ALPHA_MODES_GLOBAL_DST_ALPHA_MODE_SCALED                     0x2
+
+#define GCREG_ALPHA_MODES_SRC_BLENDING_MODE                              26 : 24
+#define GCREG_ALPHA_MODES_SRC_BLENDING_MODE_End                               26
+#define GCREG_ALPHA_MODES_SRC_BLENDING_MODE_Start                             24
+#define GCREG_ALPHA_MODES_SRC_BLENDING_MODE_Type                             U03
+#define   GCREG_ALPHA_MODES_SRC_BLENDING_MODE_ZERO                           0x0
+#define   GCREG_ALPHA_MODES_SRC_BLENDING_MODE_ONE                            0x1
+#define   GCREG_ALPHA_MODES_SRC_BLENDING_MODE_NORMAL                         0x2
+#define   GCREG_ALPHA_MODES_SRC_BLENDING_MODE_INVERSED                       0x3
+#define   GCREG_ALPHA_MODES_SRC_BLENDING_MODE_COLOR                          0x4
+#define   GCREG_ALPHA_MODES_SRC_BLENDING_MODE_COLOR_INVERSED                 0x5
+#define   GCREG_ALPHA_MODES_SRC_BLENDING_MODE_SATURATED_ALPHA                0x6
+#define   GCREG_ALPHA_MODES_SRC_BLENDING_MODE_SATURATED_DEST_ALPHA           0x7
+
+/* Src Blending factor is calculate from Src alpha. */
+#define GCREG_ALPHA_MODES_SRC_ALPHA_FACTOR                               27 : 27
+#define GCREG_ALPHA_MODES_SRC_ALPHA_FACTOR_End                                27
+#define GCREG_ALPHA_MODES_SRC_ALPHA_FACTOR_Start                              27
+#define GCREG_ALPHA_MODES_SRC_ALPHA_FACTOR_Type                              U01
+#define   GCREG_ALPHA_MODES_SRC_ALPHA_FACTOR_DISABLED                        0x0
+#define   GCREG_ALPHA_MODES_SRC_ALPHA_FACTOR_ENABLED                         0x1
+
+#define GCREG_ALPHA_MODES_DST_BLENDING_MODE                              30 : 28
+#define GCREG_ALPHA_MODES_DST_BLENDING_MODE_End                               30
+#define GCREG_ALPHA_MODES_DST_BLENDING_MODE_Start                             28
+#define GCREG_ALPHA_MODES_DST_BLENDING_MODE_Type                             U03
+#define   GCREG_ALPHA_MODES_DST_BLENDING_MODE_ZERO                           0x0
+#define   GCREG_ALPHA_MODES_DST_BLENDING_MODE_ONE                            0x1
+#define   GCREG_ALPHA_MODES_DST_BLENDING_MODE_NORMAL                         0x2
+#define   GCREG_ALPHA_MODES_DST_BLENDING_MODE_INVERSED                       0x3
+#define   GCREG_ALPHA_MODES_DST_BLENDING_MODE_COLOR                          0x4
+#define   GCREG_ALPHA_MODES_DST_BLENDING_MODE_COLOR_INVERSED                 0x5
+#define   GCREG_ALPHA_MODES_DST_BLENDING_MODE_SATURATED_ALPHA                0x6
+#define   GCREG_ALPHA_MODES_DST_BLENDING_MODE_SATURATED_DEST_ALPHA           0x7
+
+/* Dst Blending factor is calculate from Dst alpha. */
+#define GCREG_ALPHA_MODES_DST_ALPHA_FACTOR                               31 : 31
+#define GCREG_ALPHA_MODES_DST_ALPHA_FACTOR_End                                31
+#define GCREG_ALPHA_MODES_DST_ALPHA_FACTOR_Start                              31
+#define GCREG_ALPHA_MODES_DST_ALPHA_FACTOR_Type                              U01
+#define   GCREG_ALPHA_MODES_DST_ALPHA_FACTOR_DISABLED                        0x0
+#define   GCREG_ALPHA_MODES_DST_ALPHA_FACTOR_ENABLED                         0x1
+
+struct gcregalphamodes {
+	/* gcregAlphaModes:GCREG_ALPHA_MODES_SRC_ALPHA_MODE */
+	unsigned int src_inverse:1;
+
+	/* gcregAlphaModes:reserved */
+	unsigned int _reserved_1_3:3;
+
+	/* gcregAlphaModes:GCREG_ALPHA_MODES_DST_ALPHA_MODE */
+	unsigned int dst_inverse:1;
+
+	/* gcregAlphaModes:reserved */
+	unsigned int _reserved_5_7:3;
+
+	/* gcregAlphaModes:GCREG_ALPHA_MODES_GLOBAL_SRC_ALPHA_MODE */
+	unsigned int src_global_alpha_mode:2;
+
+	/* gcregAlphaModes:reserved */
+	unsigned int _reserved_10_11:2;
+
+	/* gcregAlphaModes:GCREG_ALPHA_MODES_GLOBAL_DST_ALPHA_MODE */
+	unsigned int dst_global_alpha_mode:2;
+
+	/* gcregAlphaModes:reserved */
+	unsigned int _reserved_14_23:10;
+
+	/* gcregAlphaModes:GCREG_ALPHA_MODES_SRC_BLENDING_MODE */
+	unsigned int src_blend:3;
+
+	/* gcregAlphaModes:GCREG_ALPHA_MODES_SRC_ALPHA_FACTOR */
+	unsigned int src_color_reverse:1;
+
+	/* gcregAlphaModes:GCREG_ALPHA_MODES_DST_BLENDING_MODE */
+	unsigned int dst_blend:3;
+
+	/* gcregAlphaModes:GCREG_ALPHA_MODES_DST_ALPHA_FACTOR */
+	unsigned int dst_color_reverse:1;
+};
+
+/*******************************************************************************
+** State UPlaneAddress
+*/
+
+/* 32-bit aligned base address of the source U plane. */
+
+#define gcregUPlaneAddressRegAddrs                                        0x04A1
+#define GCREG_UPLANE_ADDRESS_MSB                                              15
+#define GCREG_UPLANE_ADDRESS_LSB                                               0
+#define GCREG_UPLANE_ADDRESS_BLK                                               0
+#define GCREG_UPLANE_ADDRESS_Count                                             1
+#define GCREG_UPLANE_ADDRESS_FieldMask                                0xFFFFFFFF
+#define GCREG_UPLANE_ADDRESS_ReadMask                                 0xFFFFFFFC
+#define GCREG_UPLANE_ADDRESS_WriteMask                                0xFFFFFFFC
+#define GCREG_UPLANE_ADDRESS_ResetValue                               0x00000000
+
+#define GCREG_UPLANE_ADDRESS_ADDRESS                                      31 : 0
+#define GCREG_UPLANE_ADDRESS_ADDRESS_End                                      30
+#define GCREG_UPLANE_ADDRESS_ADDRESS_Start                                     0
+#define GCREG_UPLANE_ADDRESS_ADDRESS_Type                                    U31
+
+/*******************************************************************************
+** State UPlaneStride
+*/
+
+/* Stride of the source U plane in bytes. */
+
+#define gcregUPlaneStrideRegAddrs                                         0x04A2
+#define GCREG_UPLANE_STRIDE_MSB                                               15
+#define GCREG_UPLANE_STRIDE_LSB                                                0
+#define GCREG_UPLANE_STRIDE_BLK                                                0
+#define GCREG_UPLANE_STRIDE_Count                                              1
+#define GCREG_UPLANE_STRIDE_FieldMask                                 0x0003FFFF
+#define GCREG_UPLANE_STRIDE_ReadMask                                  0x0003FFFC
+#define GCREG_UPLANE_STRIDE_WriteMask                                 0x0003FFFC
+#define GCREG_UPLANE_STRIDE_ResetValue                                0x00000000
+
+#define GCREG_UPLANE_STRIDE_STRIDE                                        17 : 0
+#define GCREG_UPLANE_STRIDE_STRIDE_End                                        17
+#define GCREG_UPLANE_STRIDE_STRIDE_Start                                       0
+#define GCREG_UPLANE_STRIDE_STRIDE_Type                                      U18
+
+/*******************************************************************************
+** State VPlaneAddress
+*/
+
+/* 32-bit aligned base address of the source V plane. */
+
+#define gcregVPlaneAddressRegAddrs                                        0x04A3
+#define GCREG_VPLANE_ADDRESS_MSB                                              15
+#define GCREG_VPLANE_ADDRESS_LSB                                               0
+#define GCREG_VPLANE_ADDRESS_BLK                                               0
+#define GCREG_VPLANE_ADDRESS_Count                                             1
+#define GCREG_VPLANE_ADDRESS_FieldMask                                0xFFFFFFFF
+#define GCREG_VPLANE_ADDRESS_ReadMask                                 0xFFFFFFFC
+#define GCREG_VPLANE_ADDRESS_WriteMask                                0xFFFFFFFC
+#define GCREG_VPLANE_ADDRESS_ResetValue                               0x00000000
+
+#define GCREG_VPLANE_ADDRESS_ADDRESS                                      31 : 0
+#define GCREG_VPLANE_ADDRESS_ADDRESS_End                                      30
+#define GCREG_VPLANE_ADDRESS_ADDRESS_Start                                     0
+#define GCREG_VPLANE_ADDRESS_ADDRESS_Type                                    U31
+
+/*******************************************************************************
+** State VPlaneStride
+*/
+
+/* Stride of the source V plane in bytes. */
+
+#define gcregVPlaneStrideRegAddrs                                         0x04A4
+#define GCREG_VPLANE_STRIDE_MSB                                               15
+#define GCREG_VPLANE_STRIDE_LSB                                                0
+#define GCREG_VPLANE_STRIDE_BLK                                                0
+#define GCREG_VPLANE_STRIDE_Count                                              1
+#define GCREG_VPLANE_STRIDE_FieldMask                                 0x0003FFFF
+#define GCREG_VPLANE_STRIDE_ReadMask                                  0x0003FFFC
+#define GCREG_VPLANE_STRIDE_WriteMask                                 0x0003FFFC
+#define GCREG_VPLANE_STRIDE_ResetValue                                0x00000000
+
+#define GCREG_VPLANE_STRIDE_STRIDE                                        17 : 0
+#define GCREG_VPLANE_STRIDE_STRIDE_End                                        17
+#define GCREG_VPLANE_STRIDE_STRIDE_Start                                       0
+#define GCREG_VPLANE_STRIDE_STRIDE_Type                                      U18
+
+/*******************************************************************************
+** State gcregPEConfig
+*/
+
+/* PE debug register. */
+
+#define gcregPEConfigRegAddrs                                             0x04AC
+#define GCREG_PE_CONFIG_Address                                          0x012B0
+#define GCREG_PE_CONFIG_MSB                                                   15
+#define GCREG_PE_CONFIG_LSB                                                    0
+#define GCREG_PE_CONFIG_BLK                                                    0
+#define GCREG_PE_CONFIG_Count                                                  1
+#define GCREG_PE_CONFIG_FieldMask                                     0x0000000B
+#define GCREG_PE_CONFIG_ReadMask                                      0x0000000B
+#define GCREG_PE_CONFIG_WriteMask                                     0x0000000B
+#define GCREG_PE_CONFIG_ResetValue                                    0x00000000
+
+#define GCREG_PE_CONFIG_DESTINATION_FETCH                                  1 : 0
+#define GCREG_PE_CONFIG_DESTINATION_FETCH_End                                  1
+#define GCREG_PE_CONFIG_DESTINATION_FETCH_Start                                0
+#define GCREG_PE_CONFIG_DESTINATION_FETCH_Type                               U02
+#define   GCREG_PE_CONFIG_DESTINATION_FETCH_DISABLE                          0x0
+#define   GCREG_PE_CONFIG_DESTINATION_FETCH_DEFAULT                          0x1
+#define   GCREG_PE_CONFIG_DESTINATION_FETCH_ALWAYS                           0x2
+
+#define GCREG_PE_CONFIG_MASK_DESTINATION_FETCH                             3 : 3
+#define GCREG_PE_CONFIG_MASK_DESTINATION_FETCH_End                             3
+#define GCREG_PE_CONFIG_MASK_DESTINATION_FETCH_Start                           3
+#define GCREG_PE_CONFIG_MASK_DESTINATION_FETCH_Type                          U01
+#define   GCREG_PE_CONFIG_MASK_DESTINATION_FETCH_ENABLED                     0x0
+#define   GCREG_PE_CONFIG_MASK_DESTINATION_FETCH_MASKED                      0x1
+
+/*******************************************************************************
+** State gcregDstRotationHeight
+*/
+
+/* 180/270 degree rotation configuration for the destination surface. Height
+** field specifies the height of the surface in pixels.
+*/
+
+#define gcregDstRotationHeightRegAddrs                                    0x04AD
+#define GCREG_DST_ROTATION_HEIGHT_MSB                                         15
+#define GCREG_DST_ROTATION_HEIGHT_LSB                                          0
+#define GCREG_DST_ROTATION_HEIGHT_BLK                                          0
+#define GCREG_DST_ROTATION_HEIGHT_Count                                        1
+#define GCREG_DST_ROTATION_HEIGHT_FieldMask                           0x0000FFFF
+#define GCREG_DST_ROTATION_HEIGHT_ReadMask                            0x0000FFFF
+#define GCREG_DST_ROTATION_HEIGHT_WriteMask                           0x0000FFFF
+#define GCREG_DST_ROTATION_HEIGHT_ResetValue                          0x00000000
+
+#define GCREG_DST_ROTATION_HEIGHT_HEIGHT                                  15 : 0
+#define GCREG_DST_ROTATION_HEIGHT_HEIGHT_End                                  15
+#define GCREG_DST_ROTATION_HEIGHT_HEIGHT_Start                                 0
+#define GCREG_DST_ROTATION_HEIGHT_HEIGHT_Type                                U16
+
+struct gcregdstrotationheight {
+	/* gcregDstRotationHeightRegAddrs:GCREG_DST_ROTATION_HEIGHT_HEIGHT */
+	unsigned int height:16;
+
+	/* gcregDstRotationHeightRegAddrs:reserved */
+	unsigned int _reserved_16_31:16;
+};
+
+/*******************************************************************************
+** State gcregSrcRotationHeight
+*/
+
+/* 180/270 degree rotation configuration for the Source surface. Height field
+** specifies the height of the surface in pixels.
+*/
+
+#define gcregSrcRotationHeightRegAddrs                                    0x04AE
+#define GCREG_SRC_ROTATION_HEIGHT_MSB                                         15
+#define GCREG_SRC_ROTATION_HEIGHT_LSB                                          0
+#define GCREG_SRC_ROTATION_HEIGHT_BLK                                          0
+#define GCREG_SRC_ROTATION_HEIGHT_Count                                        1
+#define GCREG_SRC_ROTATION_HEIGHT_FieldMask                           0x0000FFFF
+#define GCREG_SRC_ROTATION_HEIGHT_ReadMask                            0x0000FFFF
+#define GCREG_SRC_ROTATION_HEIGHT_WriteMask                           0x0000FFFF
+#define GCREG_SRC_ROTATION_HEIGHT_ResetValue                          0x00000000
+
+#define GCREG_SRC_ROTATION_HEIGHT_HEIGHT                                  15 : 0
+#define GCREG_SRC_ROTATION_HEIGHT_HEIGHT_End                                  15
+#define GCREG_SRC_ROTATION_HEIGHT_HEIGHT_Start                                 0
+#define GCREG_SRC_ROTATION_HEIGHT_HEIGHT_Type                                U16
+
+struct gcregsrcrotationheight {
+	/* gcregSrcRotationHeightRegAddrs:GCREG_SRC_ROTATION_HEIGHT_HEIGHT */
+	unsigned int height:16;
+
+	/* gcregSrcRotationHeightRegAddrs:reserved */
+	unsigned int _reserved_16_31:16;
+};
+
+/*******************************************************************************
+** State gcregRotAngle
+*/
+
+/* 0/90/180/270 degree rotation configuration for the Source surface. Height
+** field specifies the height of the surface in pixels.
+*/
+
+#define gcregRotAngleRegAddrs                                             0x04AF
+#define GCREG_ROT_ANGLE_MSB                                                   15
+#define GCREG_ROT_ANGLE_LSB                                                    0
+#define GCREG_ROT_ANGLE_BLK                                                    0
+#define GCREG_ROT_ANGLE_Count                                                  1
+#define GCREG_ROT_ANGLE_FieldMask                                     0x000BB33F
+#define GCREG_ROT_ANGLE_ReadMask                                      0x000BB33F
+#define GCREG_ROT_ANGLE_WriteMask                                     0x000BB33F
+#define GCREG_ROT_ANGLE_ResetValue                                    0x00000000
+
+#define GCREG_ROT_ANGLE_SRC                                                2 : 0
+#define GCREG_ROT_ANGLE_SRC_End                                                2
+#define GCREG_ROT_ANGLE_SRC_Start                                              0
+#define GCREG_ROT_ANGLE_SRC_Type                                             U03
+#define   GCREG_ROT_ANGLE_SRC_ROT0                                           0x0
+#define   GCREG_ROT_ANGLE_SRC_FLIP_X                                         0x1
+#define   GCREG_ROT_ANGLE_SRC_FLIP_Y                                         0x2
+#define   GCREG_ROT_ANGLE_SRC_ROT90                                          0x4
+#define   GCREG_ROT_ANGLE_SRC_ROT180                                         0x5
+#define   GCREG_ROT_ANGLE_SRC_ROT270                                         0x6
+
+#define GCREG_ROT_ANGLE_DST                                                5 : 3
+#define GCREG_ROT_ANGLE_DST_End                                                5
+#define GCREG_ROT_ANGLE_DST_Start                                              3
+#define GCREG_ROT_ANGLE_DST_Type                                             U03
+#define   GCREG_ROT_ANGLE_DST_ROT0                                           0x0
+#define   GCREG_ROT_ANGLE_DST_FLIP_X                                         0x1
+#define   GCREG_ROT_ANGLE_DST_FLIP_Y                                         0x2
+#define   GCREG_ROT_ANGLE_DST_ROT90                                          0x4
+#define   GCREG_ROT_ANGLE_DST_ROT180                                         0x5
+#define   GCREG_ROT_ANGLE_DST_ROT270                                         0x6
+
+#define GCREG_ROT_ANGLE_MASK_SRC                                           8 : 8
+#define GCREG_ROT_ANGLE_MASK_SRC_End                                           8
+#define GCREG_ROT_ANGLE_MASK_SRC_Start                                         8
+#define GCREG_ROT_ANGLE_MASK_SRC_Type                                        U01
+#define   GCREG_ROT_ANGLE_MASK_SRC_ENABLED                                   0x0
+#define   GCREG_ROT_ANGLE_MASK_SRC_MASKED                                    0x1
+
+#define GCREG_ROT_ANGLE_MASK_DST                                           9 : 9
+#define GCREG_ROT_ANGLE_MASK_DST_End                                           9
+#define GCREG_ROT_ANGLE_MASK_DST_Start                                         9
+#define GCREG_ROT_ANGLE_MASK_DST_Type                                        U01
+#define   GCREG_ROT_ANGLE_MASK_DST_ENABLED                                   0x0
+#define   GCREG_ROT_ANGLE_MASK_DST_MASKED                                    0x1
+
+#define GCREG_ROT_ANGLE_SRC_MIRROR                                       13 : 12
+#define GCREG_ROT_ANGLE_SRC_MIRROR_End                                        13
+#define GCREG_ROT_ANGLE_SRC_MIRROR_Start                                      12
+#define GCREG_ROT_ANGLE_SRC_MIRROR_Type                                      U02
+#define   GCREG_ROT_ANGLE_SRC_MIRROR_NONE                                    0x0
+#define   GCREG_ROT_ANGLE_SRC_MIRROR_MIRROR_X                                0x1
+#define   GCREG_ROT_ANGLE_SRC_MIRROR_MIRROR_Y                                0x2
+#define   GCREG_ROT_ANGLE_SRC_MIRROR_MIRROR_XY                               0x3
+
+#define GCREG_ROT_ANGLE_MASK_SRC_MIRROR                                  15 : 15
+#define GCREG_ROT_ANGLE_MASK_SRC_MIRROR_End                                   15
+#define GCREG_ROT_ANGLE_MASK_SRC_MIRROR_Start                                 15
+#define GCREG_ROT_ANGLE_MASK_SRC_MIRROR_Type                                 U01
+#define   GCREG_ROT_ANGLE_MASK_SRC_MIRROR_ENABLED                            0x0
+#define   GCREG_ROT_ANGLE_MASK_SRC_MIRROR_MASKED                             0x1
+
+#define GCREG_ROT_ANGLE_DST_MIRROR                                       17 : 16
+#define GCREG_ROT_ANGLE_DST_MIRROR_End                                        17
+#define GCREG_ROT_ANGLE_DST_MIRROR_Start                                      16
+#define GCREG_ROT_ANGLE_DST_MIRROR_Type                                      U02
+#define   GCREG_ROT_ANGLE_DST_MIRROR_NONE                                    0x0
+#define   GCREG_ROT_ANGLE_DST_MIRROR_MIRROR_X                                0x1
+#define   GCREG_ROT_ANGLE_DST_MIRROR_MIRROR_Y                                0x2
+#define   GCREG_ROT_ANGLE_DST_MIRROR_MIRROR_XY                               0x3
+
+#define GCREG_ROT_ANGLE_MASK_DST_MIRROR                                  19 : 19
+#define GCREG_ROT_ANGLE_MASK_DST_MIRROR_End                                   19
+#define GCREG_ROT_ANGLE_MASK_DST_MIRROR_Start                                 19
+#define GCREG_ROT_ANGLE_MASK_DST_MIRROR_Type                                 U01
+#define   GCREG_ROT_ANGLE_MASK_DST_MIRROR_ENABLED                            0x0
+#define   GCREG_ROT_ANGLE_MASK_DST_MIRROR_MASKED                             0x1
+
+struct gcregrotangle {
+	/* gcregRotAngleRegAddrs:GCREG_ROT_ANGLE_SRC */
+	unsigned int src:3;
+
+	/* gcregRotAngleRegAddrs:GCREG_ROT_ANGLE_DST */
+	unsigned int dst:3;
+
+	/* gcregRotAngleRegAddrs:reserved */
+	unsigned int _reserved_6_7:2;
+
+	/* gcregRotAngleRegAddrs:GCREG_ROT_ANGLE_MASK_SRC */
+	unsigned int src_mask:1;
+
+	/* gcregRotAngleRegAddrs:GCREG_ROT_ANGLE_MASK_DST */
+	unsigned int dst_mask:1;
+
+	/* gcregRotAngleRegAddrs:reserved */
+	unsigned int _reserved_10_11:2;
+
+	/* gcregRotAngleRegAddrs:GCREG_ROT_ANGLE_SRC_MIRROR */
+	unsigned int src_mirror:2;
+
+	/* gcregRotAngleRegAddrs:reserved */
+	unsigned int _reserved_14:1;
+
+	/* gcregRotAngleRegAddrs:GCREG_ROT_ANGLE_MASK_SRC_MIRROR */
+	unsigned int src_mirror_mask:1;
+
+	/* gcregRotAngleRegAddrs:GCREG_ROT_ANGLE_DST_MIRROR */
+	unsigned int dst_mirror:2;
+
+	/* gcregRotAngleRegAddrs:reserved */
+	unsigned int _reserved_18:1;
+
+	/* gcregRotAngleRegAddrs:GCREG_ROT_ANGLE_MASK_DST_MIRROR */
+	unsigned int dst_mirror_mask:1;
+
+	/* gcregRotAngleRegAddrs:reserved */
+	unsigned int _reserved_20_31:12;
+};
+
+/*******************************************************************************
+** State gcregClearPixelValue32
+*/
+
+/* Clear color value in A8R8G8B8 format. */
+
+#define gcregClearPixelValue32RegAddrs                                    0x04B0
+#define GCREG_CLEAR_PIXEL_VALUE32_MSB                                         15
+#define GCREG_CLEAR_PIXEL_VALUE32_LSB                                          0
+#define GCREG_CLEAR_PIXEL_VALUE32_BLK                                          0
+#define GCREG_CLEAR_PIXEL_VALUE32_Count                                        1
+#define GCREG_CLEAR_PIXEL_VALUE32_FieldMask                           0xFFFFFFFF
+#define GCREG_CLEAR_PIXEL_VALUE32_ReadMask                            0xFFFFFFFF
+#define GCREG_CLEAR_PIXEL_VALUE32_WriteMask                           0xFFFFFFFF
+#define GCREG_CLEAR_PIXEL_VALUE32_ResetValue                          0x00000000
+
+#define GCREG_CLEAR_PIXEL_VALUE32_ALPHA                                  31 : 24
+#define GCREG_CLEAR_PIXEL_VALUE32_ALPHA_End                                   31
+#define GCREG_CLEAR_PIXEL_VALUE32_ALPHA_Start                                 24
+#define GCREG_CLEAR_PIXEL_VALUE32_ALPHA_Type                                 U08
+
+#define GCREG_CLEAR_PIXEL_VALUE32_RED                                    23 : 16
+#define GCREG_CLEAR_PIXEL_VALUE32_RED_End                                     23
+#define GCREG_CLEAR_PIXEL_VALUE32_RED_Start                                   16
+#define GCREG_CLEAR_PIXEL_VALUE32_RED_Type                                   U08
+
+#define GCREG_CLEAR_PIXEL_VALUE32_GREEN                                   15 : 8
+#define GCREG_CLEAR_PIXEL_VALUE32_GREEN_End                                   15
+#define GCREG_CLEAR_PIXEL_VALUE32_GREEN_Start                                  8
+#define GCREG_CLEAR_PIXEL_VALUE32_GREEN_Type                                 U08
+
+#define GCREG_CLEAR_PIXEL_VALUE32_BLUE                                     7 : 0
+#define GCREG_CLEAR_PIXEL_VALUE32_BLUE_End                                     7
+#define GCREG_CLEAR_PIXEL_VALUE32_BLUE_Start                                   0
+#define GCREG_CLEAR_PIXEL_VALUE32_BLUE_Type                                  U08
+
+struct gcregclearcolor {
+	/* gcregClearPixelValue32RegAddrs:GCREG_CLEAR_PIXEL_VALUE32_BLUE */
+	unsigned int b:8;
+
+	/* gcregClearPixelValue32RegAddrs:GCREG_CLEAR_PIXEL_VALUE32_GREEN */
+	unsigned int g:8;
+
+	/* gcregClearPixelValue32RegAddrs:GCREG_CLEAR_PIXEL_VALUE32_RED */
+	unsigned int r:8;
+
+	/* gcregClearPixelValue32RegAddrs:GCREG_CLEAR_PIXEL_VALUE32_ALPHA */
+	unsigned int a:8;
+};
+
+/*******************************************************************************
+** State gcregDestColorKey
+*/
+
+/* Defines the destination transparency color in destination format. */
+
+#define gcregDestColorKeyRegAddrs                                         0x04B1
+#define GCREG_DEST_COLOR_KEY_MSB                                              15
+#define GCREG_DEST_COLOR_KEY_LSB                                               0
+#define GCREG_DEST_COLOR_KEY_BLK                                               0
+#define GCREG_DEST_COLOR_KEY_Count                                             1
+#define GCREG_DEST_COLOR_KEY_FieldMask                                0xFFFFFFFF
+#define GCREG_DEST_COLOR_KEY_ReadMask                                 0xFFFFFFFF
+#define GCREG_DEST_COLOR_KEY_WriteMask                                0xFFFFFFFF
+#define GCREG_DEST_COLOR_KEY_ResetValue                               0x00000000
+
+#define GCREG_DEST_COLOR_KEY_ALPHA                                       31 : 24
+#define GCREG_DEST_COLOR_KEY_ALPHA_End                                        31
+#define GCREG_DEST_COLOR_KEY_ALPHA_Start                                      24
+#define GCREG_DEST_COLOR_KEY_ALPHA_Type                                      U08
+
+#define GCREG_DEST_COLOR_KEY_RED                                         23 : 16
+#define GCREG_DEST_COLOR_KEY_RED_End                                          23
+#define GCREG_DEST_COLOR_KEY_RED_Start                                        16
+#define GCREG_DEST_COLOR_KEY_RED_Type                                        U08
+
+#define GCREG_DEST_COLOR_KEY_GREEN                                        15 : 8
+#define GCREG_DEST_COLOR_KEY_GREEN_End                                        15
+#define GCREG_DEST_COLOR_KEY_GREEN_Start                                       8
+#define GCREG_DEST_COLOR_KEY_GREEN_Type                                      U08
+
+#define GCREG_DEST_COLOR_KEY_BLUE                                          7 : 0
+#define GCREG_DEST_COLOR_KEY_BLUE_End                                          7
+#define GCREG_DEST_COLOR_KEY_BLUE_Start                                        0
+#define GCREG_DEST_COLOR_KEY_BLUE_Type                                       U08
+
+/*******************************************************************************
+** State gcregGlobalSrcColor
+*/
+
+/* Defines the global source color and alpha values. */
+
+#define gcregGlobalSrcColorRegAddrs                                       0x04B2
+#define GCREG_GLOBAL_SRC_COLOR_MSB                                            15
+#define GCREG_GLOBAL_SRC_COLOR_LSB                                             0
+#define GCREG_GLOBAL_SRC_COLOR_BLK                                             0
+#define GCREG_GLOBAL_SRC_COLOR_Count                                           1
+#define GCREG_GLOBAL_SRC_COLOR_FieldMask                              0xFFFFFFFF
+#define GCREG_GLOBAL_SRC_COLOR_ReadMask                               0xFFFFFFFF
+#define GCREG_GLOBAL_SRC_COLOR_WriteMask                              0xFFFFFFFF
+#define GCREG_GLOBAL_SRC_COLOR_ResetValue                             0x00000000
+
+#define GCREG_GLOBAL_SRC_COLOR_ALPHA                                     31 : 24
+#define GCREG_GLOBAL_SRC_COLOR_ALPHA_End                                      31
+#define GCREG_GLOBAL_SRC_COLOR_ALPHA_Start                                    24
+#define GCREG_GLOBAL_SRC_COLOR_ALPHA_Type                                    U08
+
+#define GCREG_GLOBAL_SRC_COLOR_RED                                       23 : 16
+#define GCREG_GLOBAL_SRC_COLOR_RED_End                                        23
+#define GCREG_GLOBAL_SRC_COLOR_RED_Start                                      16
+#define GCREG_GLOBAL_SRC_COLOR_RED_Type                                      U08
+
+#define GCREG_GLOBAL_SRC_COLOR_GREEN                                      15 : 8
+#define GCREG_GLOBAL_SRC_COLOR_GREEN_End                                      15
+#define GCREG_GLOBAL_SRC_COLOR_GREEN_Start                                     8
+#define GCREG_GLOBAL_SRC_COLOR_GREEN_Type                                    U08
+
+#define GCREG_GLOBAL_SRC_COLOR_BLUE                                        7 : 0
+#define GCREG_GLOBAL_SRC_COLOR_BLUE_End                                        7
+#define GCREG_GLOBAL_SRC_COLOR_BLUE_Start                                      0
+#define GCREG_GLOBAL_SRC_COLOR_BLUE_Type                                     U08
+
+struct gcregglobalsrccolor {
+	/* gcregGlobalSrcColorRegAddrs:GCREG_GLOBAL_SRC_COLOR_BLUE */
+	unsigned int b:8;
+
+	/* gcregGlobalSrcColorRegAddrs:GCREG_GLOBAL_SRC_COLOR_GREEN */
+	unsigned int g:8;
+
+	/* gcregGlobalSrcColorRegAddrs:GCREG_GLOBAL_SRC_COLOR_RED */
+	unsigned int r:8;
+
+	/* gcregGlobalSrcColorRegAddrs:GCREG_GLOBAL_SRC_COLOR_ALPHA */
+	unsigned int a:8;
+};
+
+/*******************************************************************************
+** State gcregGlobalDestColor
+*/
+
+/* Defines the global destination color and alpha values. */
+
+#define gcregGlobalDestColorRegAddrs                                      0x04B3
+#define GCREG_GLOBAL_DEST_COLOR_MSB                                           15
+#define GCREG_GLOBAL_DEST_COLOR_LSB                                            0
+#define GCREG_GLOBAL_DEST_COLOR_BLK                                            0
+#define GCREG_GLOBAL_DEST_COLOR_Count                                          1
+#define GCREG_GLOBAL_DEST_COLOR_FieldMask                             0xFFFFFFFF
+#define GCREG_GLOBAL_DEST_COLOR_ReadMask                              0xFFFFFFFF
+#define GCREG_GLOBAL_DEST_COLOR_WriteMask                             0xFFFFFFFF
+#define GCREG_GLOBAL_DEST_COLOR_ResetValue                            0x00000000
+
+#define GCREG_GLOBAL_DEST_COLOR_ALPHA                                    31 : 24
+#define GCREG_GLOBAL_DEST_COLOR_ALPHA_End                                     31
+#define GCREG_GLOBAL_DEST_COLOR_ALPHA_Start                                   24
+#define GCREG_GLOBAL_DEST_COLOR_ALPHA_Type                                   U08
+
+#define GCREG_GLOBAL_DEST_COLOR_RED                                      23 : 16
+#define GCREG_GLOBAL_DEST_COLOR_RED_End                                       23
+#define GCREG_GLOBAL_DEST_COLOR_RED_Start                                     16
+#define GCREG_GLOBAL_DEST_COLOR_RED_Type                                     U08
+
+#define GCREG_GLOBAL_DEST_COLOR_GREEN                                     15 : 8
+#define GCREG_GLOBAL_DEST_COLOR_GREEN_End                                     15
+#define GCREG_GLOBAL_DEST_COLOR_GREEN_Start                                    8
+#define GCREG_GLOBAL_DEST_COLOR_GREEN_Type                                   U08
+
+#define GCREG_GLOBAL_DEST_COLOR_BLUE                                       7 : 0
+#define GCREG_GLOBAL_DEST_COLOR_BLUE_End                                       7
+#define GCREG_GLOBAL_DEST_COLOR_BLUE_Start                                     0
+#define GCREG_GLOBAL_DEST_COLOR_BLUE_Type                                    U08
+
+struct gcregglobaldstcolor {
+	/* gcregGlobalDestColorRegAddrs:GCREG_GLOBAL_DEST_COLOR_BLUE */
+	unsigned int b:8;
+
+	/* gcregGlobalDestColorRegAddrs:GCREG_GLOBAL_DEST_COLOR_GREEN */
+	unsigned int g:8;
+
+	/* gcregGlobalDestColorRegAddrs:GCREG_GLOBAL_DEST_COLOR_RED */
+	unsigned int r:8;
+
+	/* gcregGlobalDestColorRegAddrs:GCREG_GLOBAL_DEST_COLOR_ALPHA */
+	unsigned int a:8;
+};
+
+/*******************************************************************************
+** State gcregColorMultiplyModes
+*/
+
+/* Color modes to multiply Source or Destination pixel color by alpha
+** channel. Alpha can be from global color source or current pixel.
+*/
+
+#define gcregColorMultiplyModesRegAddrs                                   0x04B4
+#define GCREG_COLOR_MULTIPLY_MODES_MSB                                        15
+#define GCREG_COLOR_MULTIPLY_MODES_LSB                                         0
+#define GCREG_COLOR_MULTIPLY_MODES_BLK                                         0
+#define GCREG_COLOR_MULTIPLY_MODES_Count                                       1
+#define GCREG_COLOR_MULTIPLY_MODES_FieldMask                          0x00100311
+#define GCREG_COLOR_MULTIPLY_MODES_ReadMask                           0x00100311
+#define GCREG_COLOR_MULTIPLY_MODES_WriteMask                          0x00100311
+#define GCREG_COLOR_MULTIPLY_MODES_ResetValue                         0x00000000
+
+#define GCREG_COLOR_MULTIPLY_MODES_SRC_PREMULTIPLY                         0 : 0
+#define GCREG_COLOR_MULTIPLY_MODES_SRC_PREMULTIPLY_End                         0
+#define GCREG_COLOR_MULTIPLY_MODES_SRC_PREMULTIPLY_Start                       0
+#define GCREG_COLOR_MULTIPLY_MODES_SRC_PREMULTIPLY_Type                      U01
+#define   GCREG_COLOR_MULTIPLY_MODES_SRC_PREMULTIPLY_DISABLE                 0x0
+#define   GCREG_COLOR_MULTIPLY_MODES_SRC_PREMULTIPLY_ENABLE                  0x1
+
+#define GCREG_COLOR_MULTIPLY_MODES_DST_PREMULTIPLY                         4 : 4
+#define GCREG_COLOR_MULTIPLY_MODES_DST_PREMULTIPLY_End                         4
+#define GCREG_COLOR_MULTIPLY_MODES_DST_PREMULTIPLY_Start                       4
+#define GCREG_COLOR_MULTIPLY_MODES_DST_PREMULTIPLY_Type                      U01
+#define   GCREG_COLOR_MULTIPLY_MODES_DST_PREMULTIPLY_DISABLE                 0x0
+#define   GCREG_COLOR_MULTIPLY_MODES_DST_PREMULTIPLY_ENABLE                  0x1
+
+#define GCREG_COLOR_MULTIPLY_MODES_SRC_GLOBAL_PREMULTIPLY                  9 : 8
+#define GCREG_COLOR_MULTIPLY_MODES_SRC_GLOBAL_PREMULTIPLY_End                  9
+#define GCREG_COLOR_MULTIPLY_MODES_SRC_GLOBAL_PREMULTIPLY_Start                8
+#define GCREG_COLOR_MULTIPLY_MODES_SRC_GLOBAL_PREMULTIPLY_Type               U02
+#define   GCREG_COLOR_MULTIPLY_MODES_SRC_GLOBAL_PREMULTIPLY_DISABLE          0x0
+#define   GCREG_COLOR_MULTIPLY_MODES_SRC_GLOBAL_PREMULTIPLY_ALPHA            0x1
+#define   GCREG_COLOR_MULTIPLY_MODES_SRC_GLOBAL_PREMULTIPLY_COLOR            0x2
+
+#define GCREG_COLOR_MULTIPLY_MODES_DST_DEMULTIPLY                        20 : 20
+#define GCREG_COLOR_MULTIPLY_MODES_DST_DEMULTIPLY_End                         20
+#define GCREG_COLOR_MULTIPLY_MODES_DST_DEMULTIPLY_Start                       20
+#define GCREG_COLOR_MULTIPLY_MODES_DST_DEMULTIPLY_Type                       U01
+#define   GCREG_COLOR_MULTIPLY_MODES_DST_DEMULTIPLY_DISABLE                  0x0
+#define   GCREG_COLOR_MULTIPLY_MODES_DST_DEMULTIPLY_ENABLE                   0x1
+
+struct gcregcolormultiplymodes {
+	/* gcregColorMultiplyModesRegAddrs:
+		GCREG_COLOR_MULTIPLY_MODES_SRC_PREMULTIPLY */
+	unsigned int srcpremul:1;
+
+	/* gcregColorMultiplyModesRegAddrs:
+		reserved */
+	unsigned int _reserved_1_3:3;
+
+	/* gcregColorMultiplyModesRegAddrs:
+		GCREG_COLOR_MULTIPLY_MODES_DST_PREMULTIPLY */
+	unsigned int dstpremul:1;
+
+	/* gcregColorMultiplyModesRegAddrs:
+		reserved */
+	unsigned int _reserved_5_7:3;
+
+	/* gcregColorMultiplyModesRegAddrs:
+		GCREG_COLOR_MULTIPLY_MODES_SRC_GLOBAL_PREMULTIPLY */
+	unsigned int srcglobalpremul:2;
+
+	/* gcregColorMultiplyModesRegAddrs:
+		reserved */
+	unsigned int _reserved_10_19:10;
+
+	/* gcregColorMultiplyModesRegAddrs:
+		GCREG_COLOR_MULTIPLY_MODES_DST_DEMULTIPLY */
+	unsigned int dstdemul:1;
+
+	/* gcregColorMultiplyModesRegAddrs:
+		reserved */
+	unsigned int _reserved_21_31:11;
+};
+
+/*******************************************************************************
+** State gcregPETransparency
+*/
+
+#define gcregPETransparencyRegAddrs                                       0x04B5
+#define GCREG_PE_TRANSPARENCY_MSB                                             15
+#define GCREG_PE_TRANSPARENCY_LSB                                              0
+#define GCREG_PE_TRANSPARENCY_BLK                                              0
+#define GCREG_PE_TRANSPARENCY_Count                                            1
+#define GCREG_PE_TRANSPARENCY_FieldMask                               0xB3331333
+#define GCREG_PE_TRANSPARENCY_ReadMask                                0xB3331333
+#define GCREG_PE_TRANSPARENCY_WriteMask                               0xB3331333
+#define GCREG_PE_TRANSPARENCY_ResetValue                              0x00000000
+
+/* Source transparency mode. */
+#define GCREG_PE_TRANSPARENCY_SOURCE                                       1 : 0
+#define GCREG_PE_TRANSPARENCY_SOURCE_End                                       1
+#define GCREG_PE_TRANSPARENCY_SOURCE_Start                                     0
+#define GCREG_PE_TRANSPARENCY_SOURCE_Type                                    U02
+#define   GCREG_PE_TRANSPARENCY_SOURCE_OPAQUE                                0x0
+#define   GCREG_PE_TRANSPARENCY_SOURCE_MASK                                  0x1
+#define   GCREG_PE_TRANSPARENCY_SOURCE_KEY                                   0x2
+
+/* Pattern transparency mode. KEY transparency mode is reserved. */
+#define GCREG_PE_TRANSPARENCY_PATTERN                                      5 : 4
+#define GCREG_PE_TRANSPARENCY_PATTERN_End                                      5
+#define GCREG_PE_TRANSPARENCY_PATTERN_Start                                    4
+#define GCREG_PE_TRANSPARENCY_PATTERN_Type                                   U02
+#define   GCREG_PE_TRANSPARENCY_PATTERN_OPAQUE                               0x0
+#define   GCREG_PE_TRANSPARENCY_PATTERN_MASK                                 0x1
+#define   GCREG_PE_TRANSPARENCY_PATTERN_KEY                                  0x2
+
+/* Destination transparency mode. MASK transparency mode is reserved. */
+#define GCREG_PE_TRANSPARENCY_DESTINATION                                  9 : 8
+#define GCREG_PE_TRANSPARENCY_DESTINATION_End                                  9
+#define GCREG_PE_TRANSPARENCY_DESTINATION_Start                                8
+#define GCREG_PE_TRANSPARENCY_DESTINATION_Type                               U02
+#define   GCREG_PE_TRANSPARENCY_DESTINATION_OPAQUE                           0x0
+#define   GCREG_PE_TRANSPARENCY_DESTINATION_MASK                             0x1
+#define   GCREG_PE_TRANSPARENCY_DESTINATION_KEY                              0x2
+
+/* Mask field for Source/Pattern/Destination fields. */
+#define GCREG_PE_TRANSPARENCY_MASK_TRANSPARENCY                          12 : 12
+#define GCREG_PE_TRANSPARENCY_MASK_TRANSPARENCY_End                           12
+#define GCREG_PE_TRANSPARENCY_MASK_TRANSPARENCY_Start                         12
+#define GCREG_PE_TRANSPARENCY_MASK_TRANSPARENCY_Type                         U01
+#define   GCREG_PE_TRANSPARENCY_MASK_TRANSPARENCY_ENABLED                    0x0
+#define   GCREG_PE_TRANSPARENCY_MASK_TRANSPARENCY_MASKED                     0x1
+
+/* Source usage override. */
+#define GCREG_PE_TRANSPARENCY_USE_SRC_OVERRIDE                           17 : 16
+#define GCREG_PE_TRANSPARENCY_USE_SRC_OVERRIDE_End                            17
+#define GCREG_PE_TRANSPARENCY_USE_SRC_OVERRIDE_Start                          16
+#define GCREG_PE_TRANSPARENCY_USE_SRC_OVERRIDE_Type                          U02
+#define   GCREG_PE_TRANSPARENCY_USE_SRC_OVERRIDE_DEFAULT                     0x0
+#define   GCREG_PE_TRANSPARENCY_USE_SRC_OVERRIDE_USE_ENABLE                  0x1
+#define   GCREG_PE_TRANSPARENCY_USE_SRC_OVERRIDE_USE_DISABLE                 0x2
+
+/* Pattern usage override. */
+#define GCREG_PE_TRANSPARENCY_USE_PAT_OVERRIDE                           21 : 20
+#define GCREG_PE_TRANSPARENCY_USE_PAT_OVERRIDE_End                            21
+#define GCREG_PE_TRANSPARENCY_USE_PAT_OVERRIDE_Start                          20
+#define GCREG_PE_TRANSPARENCY_USE_PAT_OVERRIDE_Type                          U02
+#define   GCREG_PE_TRANSPARENCY_USE_PAT_OVERRIDE_DEFAULT                     0x0
+#define   GCREG_PE_TRANSPARENCY_USE_PAT_OVERRIDE_USE_ENABLE                  0x1
+#define   GCREG_PE_TRANSPARENCY_USE_PAT_OVERRIDE_USE_DISABLE                 0x2
+
+/* Destination usage override. */
+#define GCREG_PE_TRANSPARENCY_USE_DST_OVERRIDE                           25 : 24
+#define GCREG_PE_TRANSPARENCY_USE_DST_OVERRIDE_End                            25
+#define GCREG_PE_TRANSPARENCY_USE_DST_OVERRIDE_Start                          24
+#define GCREG_PE_TRANSPARENCY_USE_DST_OVERRIDE_Type                          U02
+#define   GCREG_PE_TRANSPARENCY_USE_DST_OVERRIDE_DEFAULT                     0x0
+#define   GCREG_PE_TRANSPARENCY_USE_DST_OVERRIDE_USE_ENABLE                  0x1
+#define   GCREG_PE_TRANSPARENCY_USE_DST_OVERRIDE_USE_DISABLE                 0x2
+
+/* 2D resource usage override mask field. */
+#define GCREG_PE_TRANSPARENCY_MASK_RESOURCE_OVERRIDE                     28 : 28
+#define GCREG_PE_TRANSPARENCY_MASK_RESOURCE_OVERRIDE_End                      28
+#define GCREG_PE_TRANSPARENCY_MASK_RESOURCE_OVERRIDE_Start                    28
+#define GCREG_PE_TRANSPARENCY_MASK_RESOURCE_OVERRIDE_Type                    U01
+#define   GCREG_PE_TRANSPARENCY_MASK_RESOURCE_OVERRIDE_ENABLED               0x0
+#define   GCREG_PE_TRANSPARENCY_MASK_RESOURCE_OVERRIDE_MASKED                0x1
+
+/* DEB Color Key. */
+#define GCREG_PE_TRANSPARENCY_DFB_COLOR_KEY                              29 : 29
+#define GCREG_PE_TRANSPARENCY_DFB_COLOR_KEY_End                               29
+#define GCREG_PE_TRANSPARENCY_DFB_COLOR_KEY_Start                             29
+#define GCREG_PE_TRANSPARENCY_DFB_COLOR_KEY_Type                             U01
+#define   GCREG_PE_TRANSPARENCY_DFB_COLOR_KEY_DISABLED                       0x0
+#define   GCREG_PE_TRANSPARENCY_DFB_COLOR_KEY_ENABLED                        0x1
+
+#define GCREG_PE_TRANSPARENCY_MASK_DFB_COLOR_KEY                         31 : 31
+#define GCREG_PE_TRANSPARENCY_MASK_DFB_COLOR_KEY_End                          31
+#define GCREG_PE_TRANSPARENCY_MASK_DFB_COLOR_KEY_Start                        31
+#define GCREG_PE_TRANSPARENCY_MASK_DFB_COLOR_KEY_Type                        U01
+#define   GCREG_PE_TRANSPARENCY_MASK_DFB_COLOR_KEY_ENABLED                   0x0
+#define   GCREG_PE_TRANSPARENCY_MASK_DFB_COLOR_KEY_MASKED                    0x1
+
+/*******************************************************************************
+** State gcregPEControl
+*/
+
+/* General purpose control register. */
+
+#define gcregPEControlRegAddrs                                            0x04B6
+#define GCREG_PE_CONTROL_MSB                                                  15
+#define GCREG_PE_CONTROL_LSB                                                   0
+#define GCREG_PE_CONTROL_BLK                                                   0
+#define GCREG_PE_CONTROL_Count                                                 1
+#define GCREG_PE_CONTROL_FieldMask                                    0x00000999
+#define GCREG_PE_CONTROL_ReadMask                                     0x00000999
+#define GCREG_PE_CONTROL_WriteMask                                    0x00000999
+#define GCREG_PE_CONTROL_ResetValue                                   0x00000000
+
+#define GCREG_PE_CONTROL_YUV                                               0 : 0
+#define GCREG_PE_CONTROL_YUV_End                                               0
+#define GCREG_PE_CONTROL_YUV_Start                                             0
+#define GCREG_PE_CONTROL_YUV_Type                                            U01
+#define   GCREG_PE_CONTROL_YUV_601                                           0x0
+#define   GCREG_PE_CONTROL_YUV_709                                           0x1
+
+#define GCREG_PE_CONTROL_MASK_YUV                                          3 : 3
+#define GCREG_PE_CONTROL_MASK_YUV_End                                          3
+#define GCREG_PE_CONTROL_MASK_YUV_Start                                        3
+#define GCREG_PE_CONTROL_MASK_YUV_Type                                       U01
+#define   GCREG_PE_CONTROL_MASK_YUV_ENABLED                                  0x0
+#define   GCREG_PE_CONTROL_MASK_YUV_MASKED                                   0x1
+
+#define GCREG_PE_CONTROL_UV_SWIZZLE                                        4 : 4
+#define GCREG_PE_CONTROL_UV_SWIZZLE_End                                        4
+#define GCREG_PE_CONTROL_UV_SWIZZLE_Start                                      4
+#define GCREG_PE_CONTROL_UV_SWIZZLE_Type                                     U01
+#define   GCREG_PE_CONTROL_UV_SWIZZLE_UV                                     0x0
+#define   GCREG_PE_CONTROL_UV_SWIZZLE_VU                                     0x1
+
+#define GCREG_PE_CONTROL_MASK_UV_SWIZZLE                                   7 : 7
+#define GCREG_PE_CONTROL_MASK_UV_SWIZZLE_End                                   7
+#define GCREG_PE_CONTROL_MASK_UV_SWIZZLE_Start                                 7
+#define GCREG_PE_CONTROL_MASK_UV_SWIZZLE_Type                                U01
+#define   GCREG_PE_CONTROL_MASK_UV_SWIZZLE_ENABLED                           0x0
+#define   GCREG_PE_CONTROL_MASK_UV_SWIZZLE_MASKED                            0x1
+
+/* YUV to RGB convert enable */
+#define GCREG_PE_CONTROL_YUVRGB                                            8 : 8
+#define GCREG_PE_CONTROL_YUVRGB_End                                            8
+#define GCREG_PE_CONTROL_YUVRGB_Start                                          8
+#define GCREG_PE_CONTROL_YUVRGB_Type                                         U01
+#define   GCREG_PE_CONTROL_YUVRGB_DISABLED                                   0x0
+#define   GCREG_PE_CONTROL_YUVRGB_ENABLED                                    0x1
+
+#define GCREG_PE_CONTROL_MASK_YUVRGB                                     11 : 11
+#define GCREG_PE_CONTROL_MASK_YUVRGB_End                                      11
+#define GCREG_PE_CONTROL_MASK_YUVRGB_Start                                    11
+#define GCREG_PE_CONTROL_MASK_YUVRGB_Type                                    U01
+#define   GCREG_PE_CONTROL_MASK_YUVRGB_ENABLED                               0x0
+#define   GCREG_PE_CONTROL_MASK_YUVRGB_MASKED                                0x1
+
+struct gcregpecontrol {
+	/* gcregPEControlRegAddrs:YUV */
+	unsigned int standard:1;
+
+	/* gcregPEControlRegAddrs:reserved */
+	unsigned int _reserved_1_2:2;
+
+	/* gcregPEControlRegAddrs:MASK_YUV */
+	unsigned int standard_mask:1;
+
+	/* gcregPEControlRegAddrs:UV_SWIZZLE */
+	unsigned int swizzle:1;
+
+	/* gcregPEControlRegAddrs:reserved */
+	unsigned int _reserved_5_6:2;
+
+	/* gcregPEControlRegAddrs:MASK_UV_SWIZZLE */
+	unsigned int swizzle_mask:1;
+
+	/* gcregPEControlRegAddrs:YUVRGB */
+	unsigned int convert:1;
+
+	/* gcregPEControlRegAddrs:reserved */
+	unsigned int _reserved_9_10:2;
+
+	/* gcregPEControlRegAddrs:MASK_YUVRGB */
+	unsigned int convert_mask:1;
+
+	/* gcregPEControlRegAddrs:reserved */
+	unsigned int _reserved_12_31:20;
+};
+
+/*******************************************************************************
+** State gcregSrcColorKeyHigh
+*/
+
+/* Defines the source transparency color in source format. */
+
+#define gcregSrcColorKeyHighRegAddrs                                      0x04B7
+#define GCREG_SRC_COLOR_KEY_HIGH_Address                                 0x012DC
+#define GCREG_SRC_COLOR_KEY_HIGH_MSB                                          15
+#define GCREG_SRC_COLOR_KEY_HIGH_LSB                                           0
+#define GCREG_SRC_COLOR_KEY_HIGH_BLK                                           0
+#define GCREG_SRC_COLOR_KEY_HIGH_Count                                         1
+#define GCREG_SRC_COLOR_KEY_HIGH_FieldMask                            0xFFFFFFFF
+#define GCREG_SRC_COLOR_KEY_HIGH_ReadMask                             0xFFFFFFFF
+#define GCREG_SRC_COLOR_KEY_HIGH_WriteMask                            0xFFFFFFFF
+#define GCREG_SRC_COLOR_KEY_HIGH_ResetValue                           0x00000000
+
+#define GCREG_SRC_COLOR_KEY_HIGH_ALPHA                                   31 : 24
+#define GCREG_SRC_COLOR_KEY_HIGH_ALPHA_End                                    31
+#define GCREG_SRC_COLOR_KEY_HIGH_ALPHA_Start                                  24
+#define GCREG_SRC_COLOR_KEY_HIGH_ALPHA_Type                                  U08
+
+#define GCREG_SRC_COLOR_KEY_HIGH_RED                                     23 : 16
+#define GCREG_SRC_COLOR_KEY_HIGH_RED_End                                      23
+#define GCREG_SRC_COLOR_KEY_HIGH_RED_Start                                    16
+#define GCREG_SRC_COLOR_KEY_HIGH_RED_Type                                    U08
+
+#define GCREG_SRC_COLOR_KEY_HIGH_GREEN                                    15 : 8
+#define GCREG_SRC_COLOR_KEY_HIGH_GREEN_End                                    15
+#define GCREG_SRC_COLOR_KEY_HIGH_GREEN_Start                                   8
+#define GCREG_SRC_COLOR_KEY_HIGH_GREEN_Type                                  U08
+
+#define GCREG_SRC_COLOR_KEY_HIGH_BLUE                                      7 : 0
+#define GCREG_SRC_COLOR_KEY_HIGH_BLUE_End                                      7
+#define GCREG_SRC_COLOR_KEY_HIGH_BLUE_Start                                    0
+#define GCREG_SRC_COLOR_KEY_HIGH_BLUE_Type                                   U08
+
+/*******************************************************************************
+** State gcregDestColorKeyHigh
+*/
+
+/* Defines the destination transparency color in destination format. */
+
+#define gcregDestColorKeyHighRegAddrs                                     0x04B8
+#define GCREG_DEST_COLOR_KEY_HIGH_MSB                                         15
+#define GCREG_DEST_COLOR_KEY_HIGH_LSB                                          0
+#define GCREG_DEST_COLOR_KEY_HIGH_BLK                                          0
+#define GCREG_DEST_COLOR_KEY_HIGH_Count                                        1
+#define GCREG_DEST_COLOR_KEY_HIGH_FieldMask                           0xFFFFFFFF
+#define GCREG_DEST_COLOR_KEY_HIGH_ReadMask                            0xFFFFFFFF
+#define GCREG_DEST_COLOR_KEY_HIGH_WriteMask                           0xFFFFFFFF
+#define GCREG_DEST_COLOR_KEY_HIGH_ResetValue                          0x00000000
+
+#define GCREG_DEST_COLOR_KEY_HIGH_ALPHA                                  31 : 24
+#define GCREG_DEST_COLOR_KEY_HIGH_ALPHA_End                                   31
+#define GCREG_DEST_COLOR_KEY_HIGH_ALPHA_Start                                 24
+#define GCREG_DEST_COLOR_KEY_HIGH_ALPHA_Type                                 U08
+
+#define GCREG_DEST_COLOR_KEY_HIGH_RED                                    23 : 16
+#define GCREG_DEST_COLOR_KEY_HIGH_RED_End                                     23
+#define GCREG_DEST_COLOR_KEY_HIGH_RED_Start                                   16
+#define GCREG_DEST_COLOR_KEY_HIGH_RED_Type                                   U08
+
+#define GCREG_DEST_COLOR_KEY_HIGH_GREEN                                   15 : 8
+#define GCREG_DEST_COLOR_KEY_HIGH_GREEN_End                                   15
+#define GCREG_DEST_COLOR_KEY_HIGH_GREEN_Start                                  8
+#define GCREG_DEST_COLOR_KEY_HIGH_GREEN_Type                                 U08
+
+#define GCREG_DEST_COLOR_KEY_HIGH_BLUE                                     7 : 0
+#define GCREG_DEST_COLOR_KEY_HIGH_BLUE_End                                     7
+#define GCREG_DEST_COLOR_KEY_HIGH_BLUE_Start                                   0
+#define GCREG_DEST_COLOR_KEY_HIGH_BLUE_Type                                  U08
+
+/*******************************************************************************
+** State gcregPEDitherLow
+*/
+
+/* PE dither register.
+** If you don't want dither, set all fields to their reset values.
+*/
+
+#define gcregPEDitherLowRegAddrs                                          0x04BA
+#define GCREG_PE_DITHER_LOW_MSB                                               15
+#define GCREG_PE_DITHER_LOW_LSB                                                0
+#define GCREG_PE_DITHER_LOW_BLK                                                0
+#define GCREG_PE_DITHER_LOW_Count                                              1
+#define GCREG_PE_DITHER_LOW_FieldMask                                 0xFFFFFFFF
+#define GCREG_PE_DITHER_LOW_ReadMask                                  0xFFFFFFFF
+#define GCREG_PE_DITHER_LOW_WriteMask                                 0xFFFFFFFF
+#define GCREG_PE_DITHER_LOW_ResetValue                                0xFFFFFFFF
+
+/* X,Y = 0,0 */
+#define GCREG_PE_DITHER_LOW_PIXEL_X0_Y0                                    3 : 0
+#define GCREG_PE_DITHER_LOW_PIXEL_X0_Y0_End                                    3
+#define GCREG_PE_DITHER_LOW_PIXEL_X0_Y0_Start                                  0
+#define GCREG_PE_DITHER_LOW_PIXEL_X0_Y0_Type                                 U04
+
+/* X,Y = 1,0 */
+#define GCREG_PE_DITHER_LOW_PIXEL_X1_Y0                                    7 : 4
+#define GCREG_PE_DITHER_LOW_PIXEL_X1_Y0_End                                    7
+#define GCREG_PE_DITHER_LOW_PIXEL_X1_Y0_Start                                  4
+#define GCREG_PE_DITHER_LOW_PIXEL_X1_Y0_Type                                 U04
+
+/* X,Y = 2,0 */
+#define GCREG_PE_DITHER_LOW_PIXEL_X2_Y0                                   11 : 8
+#define GCREG_PE_DITHER_LOW_PIXEL_X2_Y0_End                                   11
+#define GCREG_PE_DITHER_LOW_PIXEL_X2_Y0_Start                                  8
+#define GCREG_PE_DITHER_LOW_PIXEL_X2_Y0_Type                                 U04
+
+/* X,Y = 3,0 */
+#define GCREG_PE_DITHER_LOW_PIXEL_X3_Y0                                  15 : 12
+#define GCREG_PE_DITHER_LOW_PIXEL_X3_Y0_End                                   15
+#define GCREG_PE_DITHER_LOW_PIXEL_X3_Y0_Start                                 12
+#define GCREG_PE_DITHER_LOW_PIXEL_X3_Y0_Type                                 U04
+
+/* X,Y = 0,1 */
+#define GCREG_PE_DITHER_LOW_PIXEL_X0_Y1                                  19 : 16
+#define GCREG_PE_DITHER_LOW_PIXEL_X0_Y1_End                                   19
+#define GCREG_PE_DITHER_LOW_PIXEL_X0_Y1_Start                                 16
+#define GCREG_PE_DITHER_LOW_PIXEL_X0_Y1_Type                                 U04
+
+/* X,Y = 1,1 */
+#define GCREG_PE_DITHER_LOW_PIXEL_X1_Y1                                  23 : 20
+#define GCREG_PE_DITHER_LOW_PIXEL_X1_Y1_End                                   23
+#define GCREG_PE_DITHER_LOW_PIXEL_X1_Y1_Start                                 20
+#define GCREG_PE_DITHER_LOW_PIXEL_X1_Y1_Type                                 U04
+
+/* X,Y = 2,1 */
+#define GCREG_PE_DITHER_LOW_PIXEL_X2_Y1                                  27 : 24
+#define GCREG_PE_DITHER_LOW_PIXEL_X2_Y1_End                                   27
+#define GCREG_PE_DITHER_LOW_PIXEL_X2_Y1_Start                                 24
+#define GCREG_PE_DITHER_LOW_PIXEL_X2_Y1_Type                                 U04
+
+/* X,Y = 3,1 */
+#define GCREG_PE_DITHER_LOW_PIXEL_X3_Y1                                  31 : 28
+#define GCREG_PE_DITHER_LOW_PIXEL_X3_Y1_End                                   31
+#define GCREG_PE_DITHER_LOW_PIXEL_X3_Y1_Start                                 28
+#define GCREG_PE_DITHER_LOW_PIXEL_X3_Y1_Type                                 U04
+
+/*******************************************************************************
+** State gcregPEDitherHigh
+*/
+
+#define gcregPEDitherHighRegAddrs                                         0x04BB
+#define GCREG_PE_DITHER_HIGH_MSB                                              15
+#define GCREG_PE_DITHER_HIGH_LSB                                               0
+#define GCREG_PE_DITHER_LOW_HIGH_BLK                                           0
+#define GCREG_PE_DITHER_HIGH_Count                                             1
+#define GCREG_PE_DITHER_HIGH_FieldMask                                0xFFFFFFFF
+#define GCREG_PE_DITHER_HIGH_ReadMask                                 0xFFFFFFFF
+#define GCREG_PE_DITHER_HIGH_WriteMask                                0xFFFFFFFF
+#define GCREG_PE_DITHER_HIGH_ResetValue                               0xFFFFFFFF
+
+/* X,Y = 0,2 */
+#define GCREG_PE_DITHER_HIGH_PIXEL_X0_Y2                                   3 : 0
+#define GCREG_PE_DITHER_HIGH_PIXEL_X0_Y2_End                                   3
+#define GCREG_PE_DITHER_HIGH_PIXEL_X0_Y2_Start                                 0
+#define GCREG_PE_DITHER_HIGH_PIXEL_X0_Y2_Type                                U04
+
+/* X,Y = 1,2 */
+#define GCREG_PE_DITHER_HIGH_PIXEL_X1_Y2                                   7 : 4
+#define GCREG_PE_DITHER_HIGH_PIXEL_X1_Y2_End                                   7
+#define GCREG_PE_DITHER_HIGH_PIXEL_X1_Y2_Start                                 4
+#define GCREG_PE_DITHER_HIGH_PIXEL_X1_Y2_Type                                U04
+
+/* X,Y = 2,2 */
+#define GCREG_PE_DITHER_HIGH_PIXEL_X2_Y2                                  11 : 8
+#define GCREG_PE_DITHER_HIGH_PIXEL_X2_Y2_End                                  11
+#define GCREG_PE_DITHER_HIGH_PIXEL_X2_Y2_Start                                 8
+#define GCREG_PE_DITHER_HIGH_PIXEL_X2_Y2_Type                                U04
+
+/* X,Y = 0,3 */
+#define GCREG_PE_DITHER_HIGH_PIXEL_X3_Y2                                 15 : 12
+#define GCREG_PE_DITHER_HIGH_PIXEL_X3_Y2_End                                  15
+#define GCREG_PE_DITHER_HIGH_PIXEL_X3_Y2_Start                                12
+#define GCREG_PE_DITHER_HIGH_PIXEL_X3_Y2_Type                                U04
+
+/* X,Y = 1,3 */
+#define GCREG_PE_DITHER_HIGH_PIXEL_X0_Y3                                 19 : 16
+#define GCREG_PE_DITHER_HIGH_PIXEL_X0_Y3_End                                  19
+#define GCREG_PE_DITHER_HIGH_PIXEL_X0_Y3_Start                                16
+#define GCREG_PE_DITHER_HIGH_PIXEL_X0_Y3_Type                                U04
+
+/* X,Y = 2,3 */
+#define GCREG_PE_DITHER_HIGH_PIXEL_X1_Y3                                 23 : 20
+#define GCREG_PE_DITHER_HIGH_PIXEL_X1_Y3_End                                  23
+#define GCREG_PE_DITHER_HIGH_PIXEL_X1_Y3_Start                                20
+#define GCREG_PE_DITHER_HIGH_PIXEL_X1_Y3_Type                                U04
+
+/* X,Y = 3,3 */
+#define GCREG_PE_DITHER_HIGH_PIXEL_X2_Y3                                 27 : 24
+#define GCREG_PE_DITHER_HIGH_PIXEL_X2_Y3_End                                  27
+#define GCREG_PE_DITHER_HIGH_PIXEL_X2_Y3_Start                                24
+#define GCREG_PE_DITHER_HIGH_PIXEL_X2_Y3_Type                                U04
+
+/* X,Y = 3,2 */
+#define GCREG_PE_DITHER_HIGH_PIXEL_X3_Y3                                 31 : 28
+#define GCREG_PE_DITHER_HIGH_PIXEL_X3_Y3_End                                  31
+#define GCREG_PE_DITHER_HIGH_PIXEL_X3_Y3_Start                                28
+#define GCREG_PE_DITHER_HIGH_PIXEL_X3_Y3_Type                                U04
+
+/*******************************************************************************
+** State gcregSrcExConfig
+*/
+
+#define gcregSrcExConfigRegAddrs                                          0x04C0
+#define GCREG_SRC_EX_CONFIG_MSB                                               15
+#define GCREG_SRC_EX_CONFIG_LSB                                                0
+#define GCREG_SRC_EX_CONFIG_BLK                                                0
+#define GCREG_SRC_EX_CONFIG_Count                                              1
+#define GCREG_SRC_EX_CONFIG_FieldMask                                 0x00000109
+#define GCREG_SRC_EX_CONFIG_ReadMask                                  0x00000109
+#define GCREG_SRC_EX_CONFIG_WriteMask                                 0x00000109
+#define GCREG_SRC_EX_CONFIG_ResetValue                                0x00000000
+
+/* Source multi tiled address computation control. */
+#define GCREG_SRC_EX_CONFIG_MULTI_TILED                                    0 : 0
+#define GCREG_SRC_EX_CONFIG_MULTI_TILED_End                                    0
+#define GCREG_SRC_EX_CONFIG_MULTI_TILED_Start                                  0
+#define GCREG_SRC_EX_CONFIG_MULTI_TILED_Type                                 U01
+#define   GCREG_SRC_EX_CONFIG_MULTI_TILED_DISABLED                           0x0
+#define   GCREG_SRC_EX_CONFIG_MULTI_TILED_ENABLED                            0x1
+
+/* Source super tiled address computation control. */
+#define GCREG_SRC_EX_CONFIG_SUPER_TILED                                    3 : 3
+#define GCREG_SRC_EX_CONFIG_SUPER_TILED_End                                    3
+#define GCREG_SRC_EX_CONFIG_SUPER_TILED_Start                                  3
+#define GCREG_SRC_EX_CONFIG_SUPER_TILED_Type                                 U01
+#define   GCREG_SRC_EX_CONFIG_SUPER_TILED_DISABLED                           0x0
+#define   GCREG_SRC_EX_CONFIG_SUPER_TILED_ENABLED                            0x1
+
+/* Source super tiled address computation control. */
+#define GCREG_SRC_EX_CONFIG_MINOR_TILED                                    8 : 8
+#define GCREG_SRC_EX_CONFIG_MINOR_TILED_End                                    8
+#define GCREG_SRC_EX_CONFIG_MINOR_TILED_Start                                  8
+#define GCREG_SRC_EX_CONFIG_MINOR_TILED_Type                                 U01
+#define   GCREG_SRC_EX_CONFIG_MINOR_TILED_DISABLED                           0x0
+#define   GCREG_SRC_EX_CONFIG_MINOR_TILED_ENABLED                            0x1
+
+/* Source CacheMode. */
+#define GCREG_SRC_SRC_EX_CONFIG_CACHE_MODE                               12 : 12
+#define GCREG_SRC_SRC_EX_CONFIG_CACHE_MODE_End                                12
+#define GCREG_SRC_SRC_EX_CONFIG_CACHE_MODE_Start                              12
+#define GCREG_SRC_SRC_EX_CONFIG_CACHE_MODE_Type                              U01
+#define   GCREG_SRC_SRC_EX_CONFIG_CACHE_MODE_DISABLED                        0x0
+#define   GCREG_SRC_SRC_EX_CONFIG_CACHE_MODE_ENABLED                         0x1
+
+/*******************************************************************************
+** State gcregSrcExAddress
+*/
+
+/* 32-bit aligned base address of the source extra surface. */
+
+#define gcregSrcExAddressRegAddrs                                         0x04C1
+#define GCREG_SRC_EX_ADDRESS_MSB                                              15
+#define GCREG_SRC_EX_ADDRESS_LSB                                               0
+#define GCREG_SRC_EX_ADDRESS_BLK                                               0
+#define GCREG_SRC_EX_ADDRESS_Count                                             1
+#define GCREG_SRC_EX_ADDRESS_FieldMask                                0xFFFFFFFF
+#define GCREG_SRC_EX_ADDRESS_ReadMask                                 0xFFFFFFFC
+#define GCREG_SRC_EX_ADDRESS_WriteMask                                0xFFFFFFFC
+#define GCREG_SRC_EX_ADDRESS_ResetValue                               0x00000000
+
+#define GCREG_SRC_EX_ADDRESS_ADDRESS                                      31 : 0
+#define GCREG_SRC_EX_ADDRESS_ADDRESS_End                                      30
+#define GCREG_SRC_EX_ADDRESS_ADDRESS_Start                                     0
+#define GCREG_SRC_EX_ADDRESS_ADDRESS_Type                                    U31
+
+/*******************************************************************************
+** State gcregDEMultiSource
+*/
+
+/* MutiSource control register. */
+
+#define gcregDEMultiSourceRegAddrs                                        0x04C2
+#define GCREG_DE_MULTI_SOURCE_MSB                                             15
+#define GCREG_DE_MULTI_SOURCE_LSB                                              0
+#define GCREG_DE_MULTI_SOURCE_BLK                                              0
+#define GCREG_DE_MULTI_SOURCE_Count                                            1
+#define GCREG_DE_MULTI_SOURCE_FieldMask                               0x00070707
+#define GCREG_DE_MULTI_SOURCE_ReadMask                                0x00070707
+#define GCREG_DE_MULTI_SOURCE_WriteMask                               0x00070707
+#define GCREG_DE_MULTI_SOURCE_ResetValue                              0x00000000
+
+/* Number of source surfaces minus 1. */
+#define GCREG_DE_MULTI_SOURCE_MAX_SOURCE                                   2 : 0
+#define GCREG_DE_MULTI_SOURCE_MAX_SOURCE_End                                   2
+#define GCREG_DE_MULTI_SOURCE_MAX_SOURCE_Start                                 0
+#define GCREG_DE_MULTI_SOURCE_MAX_SOURCE_Type                                U03
+
+/* Number of pixels for horizontal block walker. */
+#define GCREG_DE_MULTI_SOURCE_HORIZONTAL_BLOCK                            10 : 8
+#define GCREG_DE_MULTI_SOURCE_HORIZONTAL_BLOCK_End                            10
+#define GCREG_DE_MULTI_SOURCE_HORIZONTAL_BLOCK_Start                           8
+#define GCREG_DE_MULTI_SOURCE_HORIZONTAL_BLOCK_Type                          U03
+#define   GCREG_DE_MULTI_SOURCE_HORIZONTAL_BLOCK_PIXEL16                     0x0
+#define   GCREG_DE_MULTI_SOURCE_HORIZONTAL_BLOCK_PIXEL32                     0x1
+#define   GCREG_DE_MULTI_SOURCE_HORIZONTAL_BLOCK_PIXEL64                     0x2
+#define   GCREG_DE_MULTI_SOURCE_HORIZONTAL_BLOCK_PIXEL128                    0x3
+#define   GCREG_DE_MULTI_SOURCE_HORIZONTAL_BLOCK_PIXEL256                    0x4
+#define   GCREG_DE_MULTI_SOURCE_HORIZONTAL_BLOCK_PIXEL512                    0x5
+
+/* Number of lines for vertical block walker. */
+#define GCREG_DE_MULTI_SOURCE_VERTICAL_BLOCK                             18 : 16
+#define GCREG_DE_MULTI_SOURCE_VERTICAL_BLOCK_End                              18
+#define GCREG_DE_MULTI_SOURCE_VERTICAL_BLOCK_Start                            16
+#define GCREG_DE_MULTI_SOURCE_VERTICAL_BLOCK_Type                            U03
+#define   GCREG_DE_MULTI_SOURCE_VERTICAL_BLOCK_LINE1                         0x0
+#define   GCREG_DE_MULTI_SOURCE_VERTICAL_BLOCK_LINE2                         0x1
+#define   GCREG_DE_MULTI_SOURCE_VERTICAL_BLOCK_LINE4                         0x2
+#define   GCREG_DE_MULTI_SOURCE_VERTICAL_BLOCK_LINE8                         0x3
+#define   GCREG_DE_MULTI_SOURCE_VERTICAL_BLOCK_LINE16                        0x4
+#define   GCREG_DE_MULTI_SOURCE_VERTICAL_BLOCK_LINE32                        0x5
+#define   GCREG_DE_MULTI_SOURCE_VERTICAL_BLOCK_LINE64                        0x6
+#define   GCREG_DE_MULTI_SOURCE_VERTICAL_BLOCK_LINE128                       0x7
+
+struct gcregmultisource {
+	/* gcregDEMultiSourceRegAddrs:GCREG_DE_MULTI_SOURCE_MAX_SOURCE */
+	unsigned int srccount:3;
+
+	/* gcregDEMultiSourceRegAddrs:reserved */
+	unsigned int _reserved_3_7:5;
+
+	/* gcregDEMultiSourceRegAddrs:GCREG_DE_MULTI_SOURCE_HORIZONTAL_BLOCK */
+	unsigned int horblock:3;
+
+	/* gcregDEMultiSourceRegAddrs:reserved */
+	unsigned int _reserved_11_15:5;
+
+	/* gcregDEMultiSourceRegAddrs:GCREG_DE_MULTI_SOURCE_VERTICAL_BLOCK */
+	unsigned int verblock:3;
+
+	/* gcregDEMultiSourceRegAddrs:reserved */
+	unsigned int _reserved_19_31:13;
+};
+
+/*******************************************************************************
+** State gcregDEYUVConversion
+*/
+
+/* Configure the YUV to YUV conversion. */
+
+#define gcregDEYUVConversionRegAddrs                                      0x04C3
+#define GCREG_DEYUV_CONVERSION_MSB                                            15
+#define GCREG_DEYUV_CONVERSION_LSB                                             0
+#define GCREG_DEYUV_CONVERSION_BLK                                             0
+#define GCREG_DEYUV_CONVERSION_Count                                           1
+#define GCREG_DEYUV_CONVERSION_FieldMask                              0xFFFFFFFF
+#define GCREG_DEYUV_CONVERSION_ReadMask                               0xFFFFFFFF
+#define GCREG_DEYUV_CONVERSION_WriteMask                              0xFFFFFFFF
+#define GCREG_DEYUV_CONVERSION_ResetValue                             0x00000000
+
+/* Select the number of planes we need to process. */
+#define GCREG_DEYUV_CONVERSION_ENABLE                                      1 : 0
+#define GCREG_DEYUV_CONVERSION_ENABLE_End                                      1
+#define GCREG_DEYUV_CONVERSION_ENABLE_Start                                    0
+#define GCREG_DEYUV_CONVERSION_ENABLE_Type                                   U02
+/* YUV to YUV conversion is turned off. */
+#define   GCREG_DEYUV_CONVERSION_ENABLE_OFF                                  0x0
+/* YUV to YUV conversion is writing to 1 plane. */
+#define   GCREG_DEYUV_CONVERSION_ENABLE_PLANE1                               0x1
+/* YUV to YUV conversion is writing to 2 planes. */
+#define   GCREG_DEYUV_CONVERSION_ENABLE_PLANE2                               0x2
+/* YUV to YUV conversion is writing to 3 planes. */
+#define   GCREG_DEYUV_CONVERSION_ENABLE_PLANE3                               0x3
+
+/* Number of channels to process - 1 for plane 1. */
+#define GCREG_DEYUV_CONVERSION_PLANE1_COUNT                                3 : 2
+#define GCREG_DEYUV_CONVERSION_PLANE1_COUNT_End                                3
+#define GCREG_DEYUV_CONVERSION_PLANE1_COUNT_Start                              2
+#define GCREG_DEYUV_CONVERSION_PLANE1_COUNT_Type                             U02
+
+/* Number of channels to process - 1 for plane 2. */
+#define GCREG_DEYUV_CONVERSION_PLANE2_COUNT                                5 : 4
+#define GCREG_DEYUV_CONVERSION_PLANE2_COUNT_End                                5
+#define GCREG_DEYUV_CONVERSION_PLANE2_COUNT_Start                              4
+#define GCREG_DEYUV_CONVERSION_PLANE2_COUNT_Type                             U02
+
+/* Number of channels to process - 1 for plane 3. */
+#define GCREG_DEYUV_CONVERSION_PLANE3_COUNT                                7 : 6
+#define GCREG_DEYUV_CONVERSION_PLANE3_COUNT_End                                7
+#define GCREG_DEYUV_CONVERSION_PLANE3_COUNT_Start                              6
+#define GCREG_DEYUV_CONVERSION_PLANE3_COUNT_Type                             U02
+
+/* Select which color channel to pick for B channel for plane 1. */
+#define GCREG_DEYUV_CONVERSION_PLANE1_SWIZZLE_B                            9 : 8
+#define GCREG_DEYUV_CONVERSION_PLANE1_SWIZZLE_B_End                            9
+#define GCREG_DEYUV_CONVERSION_PLANE1_SWIZZLE_B_Start                          8
+#define GCREG_DEYUV_CONVERSION_PLANE1_SWIZZLE_B_Type                         U02
+#define   GCREG_DEYUV_CONVERSION_PLANE1_SWIZZLE_B_BLUE                       0x0
+#define   GCREG_DEYUV_CONVERSION_PLANE1_SWIZZLE_B_GREEN                      0x1
+#define   GCREG_DEYUV_CONVERSION_PLANE1_SWIZZLE_B_RED                        0x2
+#define   GCREG_DEYUV_CONVERSION_PLANE1_SWIZZLE_B_ALPHA                      0x3
+
+/* Select which color channel to pick for G channel for plane 1. */
+#define GCREG_DEYUV_CONVERSION_PLANE1_SWIZZLE_G                          11 : 10
+#define GCREG_DEYUV_CONVERSION_PLANE1_SWIZZLE_G_End                           11
+#define GCREG_DEYUV_CONVERSION_PLANE1_SWIZZLE_G_Start                         10
+#define GCREG_DEYUV_CONVERSION_PLANE1_SWIZZLE_G_Type                         U02
+#define   GCREG_DEYUV_CONVERSION_PLANE1_SWIZZLE_G_BLUE                       0x0
+#define   GCREG_DEYUV_CONVERSION_PLANE1_SWIZZLE_G_GREEN                      0x1
+#define   GCREG_DEYUV_CONVERSION_PLANE1_SWIZZLE_G_RED                        0x2
+#define   GCREG_DEYUV_CONVERSION_PLANE1_SWIZZLE_G_ALPHA                      0x3
+
+/* Select which color channel to pick for R channel for plane 1. */
+#define GCREG_DEYUV_CONVERSION_PLANE1_SWIZZLE_R                          13 : 12
+#define GCREG_DEYUV_CONVERSION_PLANE1_SWIZZLE_R_End                           13
+#define GCREG_DEYUV_CONVERSION_PLANE1_SWIZZLE_R_Start                         12
+#define GCREG_DEYUV_CONVERSION_PLANE1_SWIZZLE_R_Type                         U02
+#define   GCREG_DEYUV_CONVERSION_PLANE1_SWIZZLE_R_BLUE                       0x0
+#define   GCREG_DEYUV_CONVERSION_PLANE1_SWIZZLE_R_GREEN                      0x1
+#define   GCREG_DEYUV_CONVERSION_PLANE1_SWIZZLE_R_RED                        0x2
+#define   GCREG_DEYUV_CONVERSION_PLANE1_SWIZZLE_R_ALPHA                      0x3
+
+/* Select which color channel to pick for A channel for plane 1. */
+#define GCREG_DEYUV_CONVERSION_PLANE1_SWIZZLE_A                          15 : 14
+#define GCREG_DEYUV_CONVERSION_PLANE1_SWIZZLE_A_End                           15
+#define GCREG_DEYUV_CONVERSION_PLANE1_SWIZZLE_A_Start                         14
+#define GCREG_DEYUV_CONVERSION_PLANE1_SWIZZLE_A_Type                         U02
+#define   GCREG_DEYUV_CONVERSION_PLANE1_SWIZZLE_A_BLUE                       0x0
+#define   GCREG_DEYUV_CONVERSION_PLANE1_SWIZZLE_A_GREEN                      0x1
+#define   GCREG_DEYUV_CONVERSION_PLANE1_SWIZZLE_A_RED                        0x2
+#define   GCREG_DEYUV_CONVERSION_PLANE1_SWIZZLE_A_ALPHA                      0x3
+
+/* Select which color channel to pick for B channel for plane 2. */
+#define GCREG_DEYUV_CONVERSION_PLANE2_SWIZZLE_B                          17 : 16
+#define GCREG_DEYUV_CONVERSION_PLANE2_SWIZZLE_B_End                           17
+#define GCREG_DEYUV_CONVERSION_PLANE2_SWIZZLE_B_Start                         16
+#define GCREG_DEYUV_CONVERSION_PLANE2_SWIZZLE_B_Type                         U02
+#define   GCREG_DEYUV_CONVERSION_PLANE2_SWIZZLE_B_BLUE                       0x0
+#define   GCREG_DEYUV_CONVERSION_PLANE2_SWIZZLE_B_GREEN                      0x1
+#define   GCREG_DEYUV_CONVERSION_PLANE2_SWIZZLE_B_RED                        0x2
+#define   GCREG_DEYUV_CONVERSION_PLANE2_SWIZZLE_B_ALPHA                      0x3
+
+/* Select which color channel to pick for G channel for plane 2. */
+#define GCREG_DEYUV_CONVERSION_PLANE2_SWIZZLE_G                          19 : 18
+#define GCREG_DEYUV_CONVERSION_PLANE2_SWIZZLE_G_End                           19
+#define GCREG_DEYUV_CONVERSION_PLANE2_SWIZZLE_G_Start                         18
+#define GCREG_DEYUV_CONVERSION_PLANE2_SWIZZLE_G_Type                         U02
+#define   GCREG_DEYUV_CONVERSION_PLANE2_SWIZZLE_G_BLUE                       0x0
+#define   GCREG_DEYUV_CONVERSION_PLANE2_SWIZZLE_G_GREEN                      0x1
+#define   GCREG_DEYUV_CONVERSION_PLANE2_SWIZZLE_G_RED                        0x2
+#define   GCREG_DEYUV_CONVERSION_PLANE2_SWIZZLE_G_ALPHA                      0x3
+
+/* Select which color channel to pick for R channel for plane 2. */
+#define GCREG_DEYUV_CONVERSION_PLANE2_SWIZZLE_R                          21 : 20
+#define GCREG_DEYUV_CONVERSION_PLANE2_SWIZZLE_R_End                           21
+#define GCREG_DEYUV_CONVERSION_PLANE2_SWIZZLE_R_Start                         20
+#define GCREG_DEYUV_CONVERSION_PLANE2_SWIZZLE_R_Type                         U02
+#define   GCREG_DEYUV_CONVERSION_PLANE2_SWIZZLE_R_BLUE                       0x0
+#define   GCREG_DEYUV_CONVERSION_PLANE2_SWIZZLE_R_GREEN                      0x1
+#define   GCREG_DEYUV_CONVERSION_PLANE2_SWIZZLE_R_RED                        0x2
+#define   GCREG_DEYUV_CONVERSION_PLANE2_SWIZZLE_R_ALPHA                      0x3
+
+/* Select which color channel to pick for A channel for plane 2. */
+#define GCREG_DEYUV_CONVERSION_PLANE2_SWIZZLE_A                          23 : 22
+#define GCREG_DEYUV_CONVERSION_PLANE2_SWIZZLE_A_End                           23
+#define GCREG_DEYUV_CONVERSION_PLANE2_SWIZZLE_A_Start                         22
+#define GCREG_DEYUV_CONVERSION_PLANE2_SWIZZLE_A_Type                         U02
+#define   GCREG_DEYUV_CONVERSION_PLANE2_SWIZZLE_A_BLUE                       0x0
+#define   GCREG_DEYUV_CONVERSION_PLANE2_SWIZZLE_A_GREEN                      0x1
+#define   GCREG_DEYUV_CONVERSION_PLANE2_SWIZZLE_A_RED                        0x2
+#define   GCREG_DEYUV_CONVERSION_PLANE2_SWIZZLE_A_ALPHA                      0x3
+
+/* Select which color channel to pick for B channel for plane 3. */
+#define GCREG_DEYUV_CONVERSION_PLANE3_SWIZZLE_B                          25 : 24
+#define GCREG_DEYUV_CONVERSION_PLANE3_SWIZZLE_B_End                           25
+#define GCREG_DEYUV_CONVERSION_PLANE3_SWIZZLE_B_Start                         24
+#define GCREG_DEYUV_CONVERSION_PLANE3_SWIZZLE_B_Type                         U02
+#define   GCREG_DEYUV_CONVERSION_PLANE3_SWIZZLE_B_BLUE                       0x0
+#define   GCREG_DEYUV_CONVERSION_PLANE3_SWIZZLE_B_GREEN                      0x1
+#define   GCREG_DEYUV_CONVERSION_PLANE3_SWIZZLE_B_RED                        0x2
+#define   GCREG_DEYUV_CONVERSION_PLANE3_SWIZZLE_B_ALPHA                      0x3
+
+/* Select which color channel to pick for G channel for plane 3. */
+#define GCREG_DEYUV_CONVERSION_PLANE3_SWIZZLE_G                          27 : 26
+#define GCREG_DEYUV_CONVERSION_PLANE3_SWIZZLE_G_End                           27
+#define GCREG_DEYUV_CONVERSION_PLANE3_SWIZZLE_G_Start                         26
+#define GCREG_DEYUV_CONVERSION_PLANE3_SWIZZLE_G_Type                         U02
+#define   GCREG_DEYUV_CONVERSION_PLANE3_SWIZZLE_G_BLUE                       0x0
+#define   GCREG_DEYUV_CONVERSION_PLANE3_SWIZZLE_G_GREEN                      0x1
+#define   GCREG_DEYUV_CONVERSION_PLANE3_SWIZZLE_G_RED                        0x2
+#define   GCREG_DEYUV_CONVERSION_PLANE3_SWIZZLE_G_ALPHA                      0x3
+
+/* Select which color channel to pick for R channel for plane 3. */
+#define GCREG_DEYUV_CONVERSION_PLANE3_SWIZZLE_R                          29 : 28
+#define GCREG_DEYUV_CONVERSION_PLANE3_SWIZZLE_R_End                           29
+#define GCREG_DEYUV_CONVERSION_PLANE3_SWIZZLE_R_Start                         28
+#define GCREG_DEYUV_CONVERSION_PLANE3_SWIZZLE_R_Type                         U02
+#define   GCREG_DEYUV_CONVERSION_PLANE3_SWIZZLE_R_BLUE                       0x0
+#define   GCREG_DEYUV_CONVERSION_PLANE3_SWIZZLE_R_GREEN                      0x1
+#define   GCREG_DEYUV_CONVERSION_PLANE3_SWIZZLE_R_RED                        0x2
+#define   GCREG_DEYUV_CONVERSION_PLANE3_SWIZZLE_R_ALPHA                      0x3
+
+/* Select which color channel to pick for A channel for plane 3. */
+#define GCREG_DEYUV_CONVERSION_PLANE3_SWIZZLE_A                          31 : 30
+#define GCREG_DEYUV_CONVERSION_PLANE3_SWIZZLE_A_End                           31
+#define GCREG_DEYUV_CONVERSION_PLANE3_SWIZZLE_A_Start                         30
+#define GCREG_DEYUV_CONVERSION_PLANE3_SWIZZLE_A_Type                         U02
+#define   GCREG_DEYUV_CONVERSION_PLANE3_SWIZZLE_A_BLUE                       0x0
+#define   GCREG_DEYUV_CONVERSION_PLANE3_SWIZZLE_A_GREEN                      0x1
+#define   GCREG_DEYUV_CONVERSION_PLANE3_SWIZZLE_A_RED                        0x2
+#define   GCREG_DEYUV_CONVERSION_PLANE3_SWIZZLE_A_ALPHA                      0x3
+
+/*******************************************************************************
+** State gcregDEPlane2Address
+*/
+
+/* Address for plane 2 if gcregDEYUVConversion.
+** Enable is set to Plane2 or Plane3.
+*/
+
+#define gcregDEPlane2AddressRegAddrs                                      0x04C4
+#define GCREG_DE_PLANE2_ADDRESS_Address                                  0x01310
+#define GCREG_DE_PLANE2_ADDRESS_MSB                                           15
+#define GCREG_DE_PLANE2_ADDRESS_LSB                                            0
+#define GCREG_DE_PLANE2_ADDRESS_BLK                                            0
+#define GCREG_DE_PLANE2_ADDRESS_Count                                          1
+#define GCREG_DE_PLANE2_ADDRESS_FieldMask                             0xFFFFFFFF
+#define GCREG_DE_PLANE2_ADDRESS_ReadMask                              0xFFFFFFFC
+#define GCREG_DE_PLANE2_ADDRESS_WriteMask                             0xFFFFFFFC
+#define GCREG_DE_PLANE2_ADDRESS_ResetValue                            0x00000000
+
+#define GCREG_DE_PLANE2_ADDRESS_ADDRESS                                   31 : 0
+#define GCREG_DE_PLANE2_ADDRESS_ADDRESS_End                                   30
+#define GCREG_DE_PLANE2_ADDRESS_ADDRESS_Start                                  0
+#define GCREG_DE_PLANE2_ADDRESS_ADDRESS_Type                                 U31
+
+/*******************************************************************************
+** State gcregDEPlane2Stride
+*/
+
+/* Stride for plane 2 if gcregDEYUVConversion.
+** Enable is set to Plane2 or Plane3.
+*/
+
+#define gcregDEPlane2StrideRegAddrs                                       0x04C5
+#define GCREG_DE_PLANE2_STRIDE_MSB                                            15
+#define GCREG_DE_PLANE2_STRIDE_LSB                                             0
+#define GCREG_DE_PLANE2_STRIDE_BLK                                             0
+#define GCREG_DE_PLANE2_STRIDE_Count                                           1
+#define GCREG_DE_PLANE2_STRIDE_FieldMask                              0x0003FFFF
+#define GCREG_DE_PLANE2_STRIDE_ReadMask                               0x0003FFFC
+#define GCREG_DE_PLANE2_STRIDE_WriteMask                              0x0003FFFC
+#define GCREG_DE_PLANE2_STRIDE_ResetValue                             0x00000000
+
+#define GCREG_DE_PLANE2_STRIDE_STRIDE                                     17 : 0
+#define GCREG_DE_PLANE2_STRIDE_STRIDE_End                                     17
+#define GCREG_DE_PLANE2_STRIDE_STRIDE_Start                                    0
+#define GCREG_DE_PLANE2_STRIDE_STRIDE_Type                                   U18
+
+/*******************************************************************************
+** State gcregDEPlane3Address
+*/
+
+/* Address for plane 3 if gcregDEYUVConversion.
+** Enable is set to Plane3.
+*/
+
+#define gcregDEPlane3AddressRegAddrs                                      0x04C6
+#define GCREG_DE_PLANE3_ADDRESS_MSB                                           15
+#define GCREG_DE_PLANE3_ADDRESS_LSB                                            0
+#define GCREG_DE_PLANE3_ADDRESS_BLK                                            0
+#define GCREG_DE_PLANE3_ADDRESS_Count                                          1
+#define GCREG_DE_PLANE3_ADDRESS_FieldMask                             0xFFFFFFFF
+#define GCREG_DE_PLANE3_ADDRESS_ReadMask                              0xFFFFFFFC
+#define GCREG_DE_PLANE3_ADDRESS_WriteMask                             0xFFFFFFFC
+#define GCREG_DE_PLANE3_ADDRESS_ResetValue                            0x00000000
+
+#define GCREG_DE_PLANE3_ADDRESS_ADDRESS                                   31 : 0
+#define GCREG_DE_PLANE3_ADDRESS_ADDRESS_End                                   30
+#define GCREG_DE_PLANE3_ADDRESS_ADDRESS_Start                                  0
+#define GCREG_DE_PLANE3_ADDRESS_ADDRESS_Type                                 U31
+
+/*******************************************************************************
+** State gcregDEPlane3Stride
+*/
+
+/* Stride for plane 3 if gcregDEYUVConversion.
+** Enable is set to Plane3.
+*/
+
+#define gcregDEPlane3StrideRegAddrs                                       0x04C7
+#define GCREG_DE_PLANE3_STRIDE_MSB                                            15
+#define GCREG_DE_PLANE3_STRIDE_LSB                                             0
+#define GCREG_DE_PLANE3_STRIDE_BLK                                             0
+#define GCREG_DE_PLANE3_STRIDE_Count                                           1
+#define GCREG_DE_PLANE3_STRIDE_FieldMask                              0x0003FFFF
+#define GCREG_DE_PLANE3_STRIDE_ReadMask                               0x0003FFFC
+#define GCREG_DE_PLANE3_STRIDE_WriteMask                              0x0003FFFC
+#define GCREG_DE_PLANE3_STRIDE_ResetValue                             0x00000000
+
+#define GCREG_DE_PLANE3_STRIDE_STRIDE                                     17 : 0
+#define GCREG_DE_PLANE3_STRIDE_STRIDE_End                                     17
+#define GCREG_DE_PLANE3_STRIDE_STRIDE_Start                                    0
+#define GCREG_DE_PLANE3_STRIDE_STRIDE_Type                                   U18
+
+/*******************************************************************************
+** State gcregDEStallDE
+*/
+
+#define gcregDEStallDERegAddrs                                            0x04C8
+#define GCREG_DE_STALL_DE_MSB                                                 15
+#define GCREG_DE_STALL_DE_LSB                                                  0
+#define GCREG_DE_STALL_DE_BLK                                                  0
+#define GCREG_DE_STALL_DE_Count                                                1
+#define GCREG_DE_STALL_DE_FieldMask                                   0x00000001
+#define GCREG_DE_STALL_DE_ReadMask                                    0x00000001
+#define GCREG_DE_STALL_DE_WriteMask                                   0x00000001
+#define GCREG_DE_STALL_DE_ResetValue                                  0x00000000
+
+/* Stall de enable. */
+#define GCREG_DE_STALL_DE_ENABLE                                           0 : 0
+#define GCREG_DE_STALL_DE_ENABLE_End                                           0
+#define GCREG_DE_STALL_DE_ENABLE_Start                                         0
+#define GCREG_DE_STALL_DE_ENABLE_Type                                        U01
+#define   GCREG_DE_STALL_DE_ENABLE_DISABLED                                  0x0
+#define   GCREG_DE_STALL_DE_ENABLE_ENABLED                                   0x1
+
+/*******************************************************************************
+** State gcregBlock4SrcAddress
+*/
+
+/* 32-bit aligned base address of the source surface. */
+
+#define gcregBlock4SrcAddressRegAddrs                                     0x4A00
+#define GCREG_BLOCK4_SRC_ADDRESS_MSB                                          15
+#define GCREG_BLOCK4_SRC_ADDRESS_LSB                                           2
+#define GCREG_BLOCK4_SRC_ADDRESS_BLK                                           0
+#define GCREG_BLOCK4_SRC_ADDRESS_Count                                         4
+#define GCREG_BLOCK4_SRC_ADDRESS_FieldMask                            0xFFFFFFFF
+#define GCREG_BLOCK4_SRC_ADDRESS_ReadMask                             0xFFFFFFFC
+#define GCREG_BLOCK4_SRC_ADDRESS_WriteMask                            0xFFFFFFFC
+#define GCREG_BLOCK4_SRC_ADDRESS_ResetValue                           0x00000000
+
+#define GCREG_BLOCK4_SRC_ADDRESS_ADDRESS                                  31 : 0
+#define GCREG_BLOCK4_SRC_ADDRESS_ADDRESS_End                                  30
+#define GCREG_BLOCK4_SRC_ADDRESS_ADDRESS_Start                                 0
+#define GCREG_BLOCK4_SRC_ADDRESS_ADDRESS_Type                                U31
+
+/*******************************************************************************
+** State gcregBlock4SrcStride
+*/
+
+/* Stride of the source surface in bytes. To calculate the stride multiply
+** the surface width in pixels by the number of  bytes per pixel.
+*/
+
+#define gcregBlock4SrcStrideRegAddrs                                      0x4A04
+#define GCREG_BLOCK4_SRC_STRIDE_MSB                                           15
+#define GCREG_BLOCK4_SRC_STRIDE_LSB                                            2
+#define GCREG_BLOCK4_SRC_STRIDE_BLK                                            0
+#define GCREG_BLOCK4_SRC_STRIDE_Count                                          4
+#define GCREG_BLOCK4_SRC_STRIDE_FieldMask                             0x0003FFFF
+#define GCREG_BLOCK4_SRC_STRIDE_ReadMask                              0x0003FFFC
+#define GCREG_BLOCK4_SRC_STRIDE_WriteMask                             0x0003FFFC
+#define GCREG_BLOCK4_SRC_STRIDE_ResetValue                            0x00000000
+
+#define GCREG_BLOCK4_SRC_STRIDE_STRIDE                                    17 : 0
+#define GCREG_BLOCK4_SRC_STRIDE_STRIDE_End                                    17
+#define GCREG_BLOCK4_SRC_STRIDE_STRIDE_Start                                   0
+#define GCREG_BLOCK4_SRC_STRIDE_STRIDE_Type                                  U18
+
+/*******************************************************************************
+** State gcregBlock4SrcRotationConfig
+*/
+
+/* 90 degree rotation configuration for the source surface. Width field
+** specifies the width of the surface in pixels.
+*/
+
+#define gcregBlock4SrcRotationConfigRegAddrs                              0x4A08
+#define GCREG_BLOCK4_SRC_ROTATION_CONFIG_MSB                                  15
+#define GCREG_BLOCK4_SRC_ROTATION_CONFIG_LSB                                   2
+#define GCREG_BLOCK4_SRC_ROTATION_CONFIG_BLK                                   0
+#define GCREG_BLOCK4_SRC_ROTATION_CONFIG_Count                                 4
+#define GCREG_BLOCK4_SRC_ROTATION_CONFIG_FieldMask                    0x0001FFFF
+#define GCREG_BLOCK4_SRC_ROTATION_CONFIG_ReadMask                     0x0001FFFF
+#define GCREG_BLOCK4_SRC_ROTATION_CONFIG_WriteMask                    0x0001FFFF
+#define GCREG_BLOCK4_SRC_ROTATION_CONFIG_ResetValue                   0x00000000
+
+#define GCREG_BLOCK4_SRC_ROTATION_CONFIG_WIDTH                            15 : 0
+#define GCREG_BLOCK4_SRC_ROTATION_CONFIG_WIDTH_End                            15
+#define GCREG_BLOCK4_SRC_ROTATION_CONFIG_WIDTH_Start                           0
+#define GCREG_BLOCK4_SRC_ROTATION_CONFIG_WIDTH_Type                          U16
+
+#define GCREG_BLOCK4_SRC_ROTATION_CONFIG_ROTATION                        16 : 16
+#define GCREG_BLOCK4_SRC_ROTATION_CONFIG_ROTATION_End                         16
+#define GCREG_BLOCK4_SRC_ROTATION_CONFIG_ROTATION_Start                       16
+#define GCREG_BLOCK4_SRC_ROTATION_CONFIG_ROTATION_Type                       U01
+#define   GCREG_BLOCK4_SRC_ROTATION_CONFIG_ROTATION_DISABLE                  0x0
+#define   GCREG_BLOCK4_SRC_ROTATION_CONFIG_ROTATION_ENABLE                   0x1
+
+/*******************************************************************************
+** State gcregBlock4SrcConfig
+*/
+
+/* Source surface configuration register. */
+
+#define gcregBlock4SrcConfigRegAddrs                                      0x4A0C
+#define GCREG_BLOCK4_SRC_CONFIG_MSB                                           15
+#define GCREG_BLOCK4_SRC_CONFIG_LSB                                            2
+#define GCREG_BLOCK4_SRC_CONFIG_BLK                                            0
+#define GCREG_BLOCK4_SRC_CONFIG_Count                                          4
+#define GCREG_BLOCK4_SRC_CONFIG_FieldMask                             0xDF30B1C0
+#define GCREG_BLOCK4_SRC_CONFIG_ReadMask                              0xDF30B1C0
+#define GCREG_BLOCK4_SRC_CONFIG_WriteMask                             0xDF30B1C0
+#define GCREG_BLOCK4_SRC_CONFIG_ResetValue                            0x00000000
+
+/* Control source endianess. */
+#define GCREG_BLOCK4_SRC_CONFIG_ENDIAN_CONTROL                           31 : 30
+#define GCREG_BLOCK4_SRC_CONFIG_ENDIAN_CONTROL_End                            31
+#define GCREG_BLOCK4_SRC_CONFIG_ENDIAN_CONTROL_Start                          30
+#define GCREG_BLOCK4_SRC_CONFIG_ENDIAN_CONTROL_Type                          U02
+#define   GCREG_BLOCK4_SRC_CONFIG_ENDIAN_CONTROL_NO_SWAP                     0x0
+#define   GCREG_BLOCK4_SRC_CONFIG_ENDIAN_CONTROL_SWAP_WORD                   0x1
+#define   GCREG_BLOCK4_SRC_CONFIG_ENDIAN_CONTROL_SWAP_DWORD                  0x2
+
+/* Defines the pixel format of the source surface. */
+#define GCREG_BLOCK4_SRC_CONFIG_SOURCE_FORMAT                            28 : 24
+#define GCREG_BLOCK4_SRC_CONFIG_SOURCE_FORMAT_End                             28
+#define GCREG_BLOCK4_SRC_CONFIG_SOURCE_FORMAT_Start                           24
+#define GCREG_BLOCK4_SRC_CONFIG_SOURCE_FORMAT_Type                           U05
+#define   GCREG_BLOCK4_SRC_CONFIG_SOURCE_FORMAT_X4R4G4B4                    0x00
+#define   GCREG_BLOCK4_SRC_CONFIG_SOURCE_FORMAT_A4R4G4B4                    0x01
+#define   GCREG_BLOCK4_SRC_CONFIG_SOURCE_FORMAT_X1R5G5B5                    0x02
+#define   GCREG_BLOCK4_SRC_CONFIG_SOURCE_FORMAT_A1R5G5B5                    0x03
+#define   GCREG_BLOCK4_SRC_CONFIG_SOURCE_FORMAT_R5G6B5                      0x04
+#define   GCREG_BLOCK4_SRC_CONFIG_SOURCE_FORMAT_X8R8G8B8                    0x05
+#define   GCREG_BLOCK4_SRC_CONFIG_SOURCE_FORMAT_A8R8G8B8                    0x06
+#define   GCREG_BLOCK4_SRC_CONFIG_SOURCE_FORMAT_YUY2                        0x07
+#define   GCREG_BLOCK4_SRC_CONFIG_SOURCE_FORMAT_UYVY                        0x08
+#define   GCREG_BLOCK4_SRC_CONFIG_SOURCE_FORMAT_INDEX8                      0x09
+#define   GCREG_BLOCK4_SRC_CONFIG_SOURCE_FORMAT_MONOCHROME                  0x0A
+#define   GCREG_BLOCK4_SRC_CONFIG_SOURCE_FORMAT_YV12                        0x0F
+#define   GCREG_BLOCK4_SRC_CONFIG_SOURCE_FORMAT_A8                          0x10
+#define   GCREG_BLOCK4_SRC_CONFIG_SOURCE_FORMAT_NV12                        0x11
+#define   GCREG_BLOCK4_SRC_CONFIG_SOURCE_FORMAT_NV16                        0x12
+#define   GCREG_BLOCK4_SRC_CONFIG_SOURCE_FORMAT_RG16                        0x13
+
+/* Color channel swizzles. */
+#define GCREG_BLOCK4_SRC_CONFIG_SWIZZLE                                  21 : 20
+#define GCREG_BLOCK4_SRC_CONFIG_SWIZZLE_End                                   21
+#define GCREG_BLOCK4_SRC_CONFIG_SWIZZLE_Start                                 20
+#define GCREG_BLOCK4_SRC_CONFIG_SWIZZLE_Type                                 U02
+#define   GCREG_BLOCK4_SRC_CONFIG_SWIZZLE_ARGB                               0x0
+#define   GCREG_BLOCK4_SRC_CONFIG_SWIZZLE_RGBA                               0x1
+#define   GCREG_BLOCK4_SRC_CONFIG_SWIZZLE_ABGR                               0x2
+#define   GCREG_BLOCK4_SRC_CONFIG_SWIZZLE_BGRA                               0x3
+
+/* Mono expansion: if 0, transparency color will be 0, otherwise transparency **
+** color will be 1.                                                           */
+#define GCREG_BLOCK4_SRC_CONFIG_MONO_TRANSPARENCY                        15 : 15
+#define GCREG_BLOCK4_SRC_CONFIG_MONO_TRANSPARENCY_End                         15
+#define GCREG_BLOCK4_SRC_CONFIG_MONO_TRANSPARENCY_Start                       15
+#define GCREG_BLOCK4_SRC_CONFIG_MONO_TRANSPARENCY_Type                       U01
+#define   GCREG_BLOCK4_SRC_CONFIG_MONO_TRANSPARENCY_BACKGROUND               0x0
+#define   GCREG_BLOCK4_SRC_CONFIG_MONO_TRANSPARENCY_FOREGROUND               0x1
+
+/* Mono expansion or masked blit: stream packing in pixels. Determines how    **
+** many horizontal pixels are there per each 32-bit chunk. For example, if    **
+** set to Packed8, each 32-bit chunk is 8-pixel wide, which also means that   **
+** it defines 4 vertical lines of pixels.                                     */
+#define GCREG_BLOCK4_SRC_CONFIG_PACK                                     13 : 12
+#define GCREG_BLOCK4_SRC_CONFIG_PACK_End                                      13
+#define GCREG_BLOCK4_SRC_CONFIG_PACK_Start                                    12
+#define GCREG_BLOCK4_SRC_CONFIG_PACK_Type                                    U02
+#define   GCREG_BLOCK4_SRC_CONFIG_PACK_PACKED8                               0x0
+#define   GCREG_BLOCK4_SRC_CONFIG_PACK_PACKED16                              0x1
+#define   GCREG_BLOCK4_SRC_CONFIG_PACK_PACKED32                              0x2
+#define   GCREG_BLOCK4_SRC_CONFIG_PACK_UNPACKED                              0x3
+
+/* Source data location: set to STREAM for mono expansion blits or masked     **
+** blits. For mono expansion blits the complete bitmap comes from the command **
+** stream. For masked blits the source data comes from the memory and the     **
+** mask from the command stream.                                              */
+#define GCREG_BLOCK4_SRC_CONFIG_LOCATION                                   8 : 8
+#define GCREG_BLOCK4_SRC_CONFIG_LOCATION_End                                   8
+#define GCREG_BLOCK4_SRC_CONFIG_LOCATION_Start                                 8
+#define GCREG_BLOCK4_SRC_CONFIG_LOCATION_Type                                U01
+#define   GCREG_BLOCK4_SRC_CONFIG_LOCATION_MEMORY                            0x0
+#define   GCREG_BLOCK4_SRC_CONFIG_LOCATION_STREAM                            0x1
+
+/* Source linear/tiled address computation control. */
+#define GCREG_BLOCK4_SRC_CONFIG_TILED                                      7 : 7
+#define GCREG_BLOCK4_SRC_CONFIG_TILED_End                                      7
+#define GCREG_BLOCK4_SRC_CONFIG_TILED_Start                                    7
+#define GCREG_BLOCK4_SRC_CONFIG_TILED_Type                                   U01
+#define   GCREG_BLOCK4_SRC_CONFIG_TILED_DISABLED                             0x0
+#define   GCREG_BLOCK4_SRC_CONFIG_TILED_ENABLED                              0x1
+
+/* If set to ABSOLUTE, the source coordinates are treated as absolute         **
+** coordinates inside the source surface. If set to RELATIVE, the source      **
+** coordinates are treated as the offsets from the destination coordinates    **
+** with the source size equal to the size of the destination.                 */
+#define GCREG_BLOCK4_SRC_CONFIG_SRC_RELATIVE                               6 : 6
+#define GCREG_BLOCK4_SRC_CONFIG_SRC_RELATIVE_End                               6
+#define GCREG_BLOCK4_SRC_CONFIG_SRC_RELATIVE_Start                             6
+#define GCREG_BLOCK4_SRC_CONFIG_SRC_RELATIVE_Type                            U01
+#define   GCREG_BLOCK4_SRC_CONFIG_SRC_RELATIVE_ABSOLUTE                      0x0
+#define   GCREG_BLOCK4_SRC_CONFIG_SRC_RELATIVE_RELATIVE                      0x1
+
+/*******************************************************************************
+** State gcregBlock4SrcOrigin
+*/
+
+/* Absolute or relative (see SRC_RELATIVE field of gcregBlock4SrcConfig
+** register) X and Y coordinates in pixels of the top left corner of the
+** source rectangle within the source surface.
+*/
+
+#define gcregBlock4SrcOriginRegAddrs                                      0x4A10
+#define GCREG_BLOCK4_SRC_ORIGIN_MSB                                           15
+#define GCREG_BLOCK4_SRC_ORIGIN_LSB                                            2
+#define GCREG_BLOCK4_SRC_ORIGIN_BLK                                            0
+#define GCREG_BLOCK4_SRC_ORIGIN_Count                                          4
+#define GCREG_BLOCK4_SRC_ORIGIN_FieldMask                             0xFFFFFFFF
+#define GCREG_BLOCK4_SRC_ORIGIN_ReadMask                              0xFFFFFFFF
+#define GCREG_BLOCK4_SRC_ORIGIN_WriteMask                             0xFFFFFFFF
+#define GCREG_BLOCK4_SRC_ORIGIN_ResetValue                            0x00000000
+
+#define GCREG_BLOCK4_SRC_ORIGIN_Y                                        31 : 16
+#define GCREG_BLOCK4_SRC_ORIGIN_Y_End                                         31
+#define GCREG_BLOCK4_SRC_ORIGIN_Y_Start                                       16
+#define GCREG_BLOCK4_SRC_ORIGIN_Y_Type                                       U16
+
+#define GCREG_BLOCK4_SRC_ORIGIN_X                                         15 : 0
+#define GCREG_BLOCK4_SRC_ORIGIN_X_End                                         15
+#define GCREG_BLOCK4_SRC_ORIGIN_X_Start                                        0
+#define GCREG_BLOCK4_SRC_ORIGIN_X_Type                                       U16
+
+/*******************************************************************************
+** State gcregBlock4SrcSize
+*/
+
+/* Width and height of the source rectangle in pixels. If the source is
+** relative (see SRC_RELATIVE field of gcregBlock4SrcConfig register) or a
+** regular bitblt is being performed without stretching, this register is
+** ignored and the source size is assumed to be the same as the destination.
+*/
+
+#define gcregBlock4SrcSizeRegAddrs                                        0x4A14
+#define GCREG_BLOCK4_SRC_SIZE_MSB                                             15
+#define GCREG_BLOCK4_SRC_SIZE_LSB                                              2
+#define GCREG_BLOCK4_SRC_SIZE_BLK                                              0
+#define GCREG_BLOCK4_SRC_SIZE_Count                                            4
+#define GCREG_BLOCK4_SRC_SIZE_FieldMask                               0xFFFFFFFF
+#define GCREG_BLOCK4_SRC_SIZE_ReadMask                                0xFFFFFFFF
+#define GCREG_BLOCK4_SRC_SIZE_WriteMask                               0xFFFFFFFF
+#define GCREG_BLOCK4_SRC_SIZE_ResetValue                              0x00000000
+
+#define GCREG_BLOCK4_SRC_SIZE_Y                                          31 : 16
+#define GCREG_BLOCK4_SRC_SIZE_Y_End                                           31
+#define GCREG_BLOCK4_SRC_SIZE_Y_Start                                         16
+#define GCREG_BLOCK4_SRC_SIZE_Y_Type                                         U16
+
+#define GCREG_BLOCK4_SRC_SIZE_X                                           15 : 0
+#define GCREG_BLOCK4_SRC_SIZE_X_End                                           15
+#define GCREG_BLOCK4_SRC_SIZE_X_Start                                          0
+#define GCREG_BLOCK4_SRC_SIZE_X_Type                                         U16
+
+/*******************************************************************************
+** State gcregBlock4SrcColorBg
+*/
+
+/* Select the color where source becomes transparent. It must be programmed
+** in A8R8G8B8 format.
+*/
+
+#define gcregBlock4SrcColorBgRegAddrs                                     0x4A18
+#define GCREG_BLOCK4_SRC_COLOR_BG_MSB                                         15
+#define GCREG_BLOCK4_SRC_COLOR_BG_LSB                                          2
+#define GCREG_BLOCK4_SRC_COLOR_BG_BLK                                          0
+#define GCREG_BLOCK4_SRC_COLOR_BG_Count                                        4
+#define GCREG_BLOCK4_SRC_COLOR_BG_FieldMask                           0xFFFFFFFF
+#define GCREG_BLOCK4_SRC_COLOR_BG_ReadMask                            0xFFFFFFFF
+#define GCREG_BLOCK4_SRC_COLOR_BG_WriteMask                           0xFFFFFFFF
+#define GCREG_BLOCK4_SRC_COLOR_BG_ResetValue                          0x00000000
+
+#define GCREG_BLOCK4_SRC_COLOR_BG_ALPHA                                  31 : 24
+#define GCREG_BLOCK4_SRC_COLOR_BG_ALPHA_End                                   31
+#define GCREG_BLOCK4_SRC_COLOR_BG_ALPHA_Start                                 24
+#define GCREG_BLOCK4_SRC_COLOR_BG_ALPHA_Type                                 U08
+
+#define GCREG_BLOCK4_SRC_COLOR_BG_RED                                    23 : 16
+#define GCREG_BLOCK4_SRC_COLOR_BG_RED_End                                     23
+#define GCREG_BLOCK4_SRC_COLOR_BG_RED_Start                                   16
+#define GCREG_BLOCK4_SRC_COLOR_BG_RED_Type                                   U08
+
+#define GCREG_BLOCK4_SRC_COLOR_BG_GREEN                                   15 : 8
+#define GCREG_BLOCK4_SRC_COLOR_BG_GREEN_End                                   15
+#define GCREG_BLOCK4_SRC_COLOR_BG_GREEN_Start                                  8
+#define GCREG_BLOCK4_SRC_COLOR_BG_GREEN_Type                                 U08
+
+#define GCREG_BLOCK4_SRC_COLOR_BG_BLUE                                     7 : 0
+#define GCREG_BLOCK4_SRC_COLOR_BG_BLUE_End                                     7
+#define GCREG_BLOCK4_SRC_COLOR_BG_BLUE_Start                                   0
+#define GCREG_BLOCK4_SRC_COLOR_BG_BLUE_Type                                  U08
+
+/*******************************************************************************
+** State gcregBlock4Rop
+*/
+
+/* Raster operation foreground and background codes. Even though ROP is not
+** used in CLEAR, HOR_FILTER_BLT, VER_FILTER_BLT and alpha-eanbled BIT_BLTs,
+** ROP code still has to be programmed, because the engine makes the decision
+** whether source, destination and pattern are involved in the current
+** operation and the correct decision is essential for the engine to complete
+** the operation as expected.
+*/
+
+#define gcregBlock4RopRegAddrs                                            0x4A1C
+#define GCREG_BLOCK4_ROP_MSB                                                  15
+#define GCREG_BLOCK4_ROP_LSB                                                   2
+#define GCREG_BLOCK4_ROP_BLK                                                   0
+#define GCREG_BLOCK4_ROP_Count                                                 4
+#define GCREG_BLOCK4_ROP_FieldMask                                    0x0030FFFF
+#define GCREG_BLOCK4_ROP_ReadMask                                     0x0030FFFF
+#define GCREG_BLOCK4_ROP_WriteMask                                    0x0030FFFF
+#define GCREG_BLOCK4_ROP_ResetValue                                   0x00000000
+
+/* ROP type: ROP2, ROP3 or ROP4 */
+#define GCREG_BLOCK4_ROP_TYPE                                            21 : 20
+#define GCREG_BLOCK4_ROP_TYPE_End                                             21
+#define GCREG_BLOCK4_ROP_TYPE_Start                                           20
+#define GCREG_BLOCK4_ROP_TYPE_Type                                           U02
+#define   GCREG_BLOCK4_ROP_TYPE_ROP2_PATTERN                                 0x0
+#define   GCREG_BLOCK4_ROP_TYPE_ROP2_SOURCE                                  0x1
+#define   GCREG_BLOCK4_ROP_TYPE_ROP3                                         0x2
+#define   GCREG_BLOCK4_ROP_TYPE_ROP4                                         0x3
+
+/* Background ROP code is used for transparent pixels. */
+#define GCREG_BLOCK4_ROP_ROP_BG                                           15 : 8
+#define GCREG_BLOCK4_ROP_ROP_BG_End                                           15
+#define GCREG_BLOCK4_ROP_ROP_BG_Start                                          8
+#define GCREG_BLOCK4_ROP_ROP_BG_Type                                         U08
+
+/* Background ROP code is used for opaque pixels. */
+#define GCREG_BLOCK4_ROP_ROP_FG                                            7 : 0
+#define GCREG_BLOCK4_ROP_ROP_FG_End                                            7
+#define GCREG_BLOCK4_ROP_ROP_FG_Start                                          0
+#define GCREG_BLOCK4_ROP_ROP_FG_Type                                         U08
+
+/*******************************************************************************
+** State gcregBlock4AlphaControl
+*/
+
+#define gcregBlock4AlphaControlRegAddrs                                   0x4A20
+#define GCREG_BLOCK4_ALPHA_CONTROL_MSB                                        15
+#define GCREG_BLOCK4_ALPHA_CONTROL_LSB                                         2
+#define GCREG_BLOCK4_ALPHA_CONTROL_BLK                                         0
+#define GCREG_BLOCK4_ALPHA_CONTROL_Count                                       4
+#define GCREG_BLOCK4_ALPHA_CONTROL_FieldMask                          0x00000001
+#define GCREG_BLOCK4_ALPHA_CONTROL_ReadMask                           0x00000001
+#define GCREG_BLOCK4_ALPHA_CONTROL_WriteMask                          0x00000001
+#define GCREG_BLOCK4_ALPHA_CONTROL_ResetValue                         0x00000000
+
+#define GCREG_BLOCK4_ALPHA_CONTROL_ENABLE                                  0 : 0
+#define GCREG_BLOCK4_ALPHA_CONTROL_ENABLE_End                                  0
+#define GCREG_BLOCK4_ALPHA_CONTROL_ENABLE_Start                                0
+#define GCREG_BLOCK4_ALPHA_CONTROL_ENABLE_Type                               U01
+#define   GCREG_BLOCK4_ALPHA_CONTROL_ENABLE_OFF                              0x0
+#define   GCREG_BLOCK4_ALPHA_CONTROL_ENABLE_ON                               0x1
+
+/*******************************************************************************
+** State gcregBlock4AlphaModes
+*/
+
+#define gcregBlock4AlphaModesRegAddrs                                     0x4A24
+#define GCREG_BLOCK4_ALPHA_MODES_MSB                                          15
+#define GCREG_BLOCK4_ALPHA_MODES_LSB                                           2
+#define GCREG_BLOCK4_ALPHA_MODES_BLK                                           0
+#define GCREG_BLOCK4_ALPHA_MODES_Count                                         4
+#define GCREG_BLOCK4_ALPHA_MODES_FieldMask                            0xFF003311
+#define GCREG_BLOCK4_ALPHA_MODES_ReadMask                             0xFF003311
+#define GCREG_BLOCK4_ALPHA_MODES_WriteMask                            0xFF003311
+#define GCREG_BLOCK4_ALPHA_MODES_ResetValue                           0x00000000
+
+#define GCREG_BLOCK4_ALPHA_MODES_SRC_ALPHA_MODE                            0 : 0
+#define GCREG_BLOCK4_ALPHA_MODES_SRC_ALPHA_MODE_End                            0
+#define GCREG_BLOCK4_ALPHA_MODES_SRC_ALPHA_MODE_Start                          0
+#define GCREG_BLOCK4_ALPHA_MODES_SRC_ALPHA_MODE_Type                         U01
+#define   GCREG_BLOCK4_ALPHA_MODES_SRC_ALPHA_MODE_NORMAL                     0x0
+#define   GCREG_BLOCK4_ALPHA_MODES_SRC_ALPHA_MODE_INVERSED                   0x1
+
+#define GCREG_BLOCK4_ALPHA_MODES_DST_ALPHA_MODE                            4 : 4
+#define GCREG_BLOCK4_ALPHA_MODES_DST_ALPHA_MODE_End                            4
+#define GCREG_BLOCK4_ALPHA_MODES_DST_ALPHA_MODE_Start                          4
+#define GCREG_BLOCK4_ALPHA_MODES_DST_ALPHA_MODE_Type                         U01
+#define   GCREG_BLOCK4_ALPHA_MODES_DST_ALPHA_MODE_NORMAL                     0x0
+#define   GCREG_BLOCK4_ALPHA_MODES_DST_ALPHA_MODE_INVERSED                   0x1
+
+#define GCREG_BLOCK4_ALPHA_MODES_GLOBAL_SRC_ALPHA_MODE                     9 : 8
+#define GCREG_BLOCK4_ALPHA_MODES_GLOBAL_SRC_ALPHA_MODE_End                     9
+#define GCREG_BLOCK4_ALPHA_MODES_GLOBAL_SRC_ALPHA_MODE_Start                   8
+#define GCREG_BLOCK4_ALPHA_MODES_GLOBAL_SRC_ALPHA_MODE_Type                  U02
+#define   GCREG_BLOCK4_ALPHA_MODES_GLOBAL_SRC_ALPHA_MODE_NORMAL              0x0
+#define   GCREG_BLOCK4_ALPHA_MODES_GLOBAL_SRC_ALPHA_MODE_GLOBAL              0x1
+#define   GCREG_BLOCK4_ALPHA_MODES_GLOBAL_SRC_ALPHA_MODE_SCALED              0x2
+
+#define GCREG_BLOCK4_ALPHA_MODES_GLOBAL_DST_ALPHA_MODE                   13 : 12
+#define GCREG_BLOCK4_ALPHA_MODES_GLOBAL_DST_ALPHA_MODE_End                    13
+#define GCREG_BLOCK4_ALPHA_MODES_GLOBAL_DST_ALPHA_MODE_Start                  12
+#define GCREG_BLOCK4_ALPHA_MODES_GLOBAL_DST_ALPHA_MODE_Type                  U02
+#define   GCREG_BLOCK4_ALPHA_MODES_GLOBAL_DST_ALPHA_MODE_NORMAL              0x0
+#define   GCREG_BLOCK4_ALPHA_MODES_GLOBAL_DST_ALPHA_MODE_GLOBAL              0x1
+#define   GCREG_BLOCK4_ALPHA_MODES_GLOBAL_DST_ALPHA_MODE_SCALED              0x2
+
+#define GCREG_BLOCK4_ALPHA_MODES_SRC_BLENDING_MODE                       26 : 24
+#define GCREG_BLOCK4_ALPHA_MODES_SRC_BLENDING_MODE_End                        26
+#define GCREG_BLOCK4_ALPHA_MODES_SRC_BLENDING_MODE_Start                      24
+#define GCREG_BLOCK4_ALPHA_MODES_SRC_BLENDING_MODE_Type                      U03
+#define   GCREG_BLOCK4_ALPHA_MODES_SRC_BLENDING_MODE_ZERO                    0x0
+#define   GCREG_BLOCK4_ALPHA_MODES_SRC_BLENDING_MODE_ONE                     0x1
+#define   GCREG_BLOCK4_ALPHA_MODES_SRC_BLENDING_MODE_NORMAL                  0x2
+#define   GCREG_BLOCK4_ALPHA_MODES_SRC_BLENDING_MODE_INVERSED                0x3
+#define   GCREG_BLOCK4_ALPHA_MODES_SRC_BLENDING_MODE_COLOR                   0x4
+#define   GCREG_BLOCK4_ALPHA_MODES_SRC_BLENDING_MODE_COLOR_INVERSED          0x5
+#define   GCREG_BLOCK4_ALPHA_MODES_SRC_BLENDING_MODE_SATURATED_ALPHA         0x6
+#define   GCREG_BLOCK4_ALPHA_MODES_SRC_BLENDING_MODE_SATURATED_DEST_ALPHA    0x7
+
+/* Src Blending factor is calculate from Src alpha. */
+#define GCREG_BLOCK4_ALPHA_MODES_SRC_ALPHA_FACTOR                        27 : 27
+#define GCREG_BLOCK4_ALPHA_MODES_SRC_ALPHA_FACTOR_End                         27
+#define GCREG_BLOCK4_ALPHA_MODES_SRC_ALPHA_FACTOR_Start                       27
+#define GCREG_BLOCK4_ALPHA_MODES_SRC_ALPHA_FACTOR_Type                       U01
+#define   GCREG_BLOCK4_ALPHA_MODES_SRC_ALPHA_FACTOR_DISABLED                 0x0
+#define   GCREG_BLOCK4_ALPHA_MODES_SRC_ALPHA_FACTOR_ENABLED                  0x1
+
+#define GCREG_BLOCK4_ALPHA_MODES_DST_BLENDING_MODE                       30 : 28
+#define GCREG_BLOCK4_ALPHA_MODES_DST_BLENDING_MODE_End                        30
+#define GCREG_BLOCK4_ALPHA_MODES_DST_BLENDING_MODE_Start                      28
+#define GCREG_BLOCK4_ALPHA_MODES_DST_BLENDING_MODE_Type                      U03
+#define   GCREG_BLOCK4_ALPHA_MODES_DST_BLENDING_MODE_ZERO                    0x0
+#define   GCREG_BLOCK4_ALPHA_MODES_DST_BLENDING_MODE_ONE                     0x1
+#define   GCREG_BLOCK4_ALPHA_MODES_DST_BLENDING_MODE_NORMAL                  0x2
+#define   GCREG_BLOCK4_ALPHA_MODES_DST_BLENDING_MODE_INVERSED                0x3
+#define   GCREG_BLOCK4_ALPHA_MODES_DST_BLENDING_MODE_COLOR                   0x4
+#define   GCREG_BLOCK4_ALPHA_MODES_DST_BLENDING_MODE_COLOR_INVERSED          0x5
+#define   GCREG_BLOCK4_ALPHA_MODES_DST_BLENDING_MODE_SATURATED_ALPHA         0x6
+#define   GCREG_BLOCK4_ALPHA_MODES_DST_BLENDING_MODE_SATURATED_DEST_ALPHA    0x7
+
+/* Dst Blending factor is calculate from Dst alpha. */
+#define GCREG_BLOCK4_ALPHA_MODES_DST_ALPHA_FACTOR                        31 : 31
+#define GCREG_BLOCK4_ALPHA_MODES_DST_ALPHA_FACTOR_End                         31
+#define GCREG_BLOCK4_ALPHA_MODES_DST_ALPHA_FACTOR_Start                       31
+#define GCREG_BLOCK4_ALPHA_MODES_DST_ALPHA_FACTOR_Type                       U01
+#define   GCREG_BLOCK4_ALPHA_MODES_DST_ALPHA_FACTOR_DISABLED                 0x0
+#define   GCREG_BLOCK4_ALPHA_MODES_DST_ALPHA_FACTOR_ENABLED                  0x1
+
+/*******************************************************************************
+** State gcregBlock4AddressU
+*/
+
+/* 32-bit aligned base address of the source U plane. */
+
+#define gcregBlock4UPlaneAddressRegAddrs                                  0x4A28
+#define GCREG_BLOCK4_UPLANE_ADDRESS_MSB                                       15
+#define GCREG_BLOCK4_UPLANE_ADDRESS_LSB                                        2
+#define GCREG_BLOCK4_UPLANE_ADDRESS_BLK                                        0
+#define GCREG_BLOCK4_UPLANE_ADDRESS_Count                                      4
+#define GCREG_BLOCK4_UPLANE_ADDRESS_FieldMask                         0xFFFFFFFF
+#define GCREG_BLOCK4_UPLANE_ADDRESS_ReadMask                          0xFFFFFFFC
+#define GCREG_BLOCK4_UPLANE_ADDRESS_WriteMask                         0xFFFFFFFC
+#define GCREG_BLOCK4_UPLANE_ADDRESS_ResetValue                        0x00000000
+
+#define GCREG_BLOCK4_UPLANE_ADDRESS_ADDRESS                               31 : 0
+#define GCREG_BLOCK4_UPLANE_ADDRESS_ADDRESS_End                               30
+#define GCREG_BLOCK4_UPLANE_ADDRESS_ADDRESS_Start                              0
+#define GCREG_BLOCK4_UPLANE_ADDRESS_ADDRESS_Type                             U31
+
+/*******************************************************************************
+** State gcregBlock4StrideU
+*/
+
+/* Stride of the source U plane in bytes. */
+
+#define gcregBlock4UPlaneStrideRegAddrs                                   0x4A2C
+#define GCREG_BLOCK4_UPLANE_STRIDE_MSB                                        15
+#define GCREG_BLOCK4_UPLANE_STRIDE_LSB                                         2
+#define GCREG_BLOCK4_UPLANE_STRIDE_BLK                                         0
+#define GCREG_BLOCK4_UPLANE_STRIDE_Count                                       4
+#define GCREG_BLOCK4_UPLANE_STRIDE_FieldMask                          0x0003FFFF
+#define GCREG_BLOCK4_UPLANE_STRIDE_ReadMask                           0x0003FFFC
+#define GCREG_BLOCK4_UPLANE_STRIDE_WriteMask                          0x0003FFFC
+#define GCREG_BLOCK4_UPLANE_STRIDE_ResetValue                         0x00000000
+
+#define GCREG_BLOCK4_UPLANE_STRIDE_STRIDE                                 17 : 0
+#define GCREG_BLOCK4_UPLANE_STRIDE_STRIDE_End                                 17
+#define GCREG_BLOCK4_UPLANE_STRIDE_STRIDE_Start                                0
+#define GCREG_BLOCK4_UPLANE_STRIDE_STRIDE_Type                               U18
+
+/*******************************************************************************
+** State gcregBlock4AddressV
+*/
+
+/* 32-bit aligned base address of the source V plane. */
+
+#define gcregBlock4VPlaneAddressRegAddrs                                  0x4A30
+#define GCREG_BLOCK4_VPLANE_ADDRESS_MSB                                       15
+#define GCREG_BLOCK4_VPLANE_ADDRESS_LSB                                        2
+#define GCREG_BLOCK4_VPLANE_ADDRESS_BLK                                        0
+#define GCREG_BLOCK4_VPLANE_ADDRESS_Count                                      4
+#define GCREG_BLOCK4_VPLANE_ADDRESS_FieldMask                         0xFFFFFFFF
+#define GCREG_BLOCK4_VPLANE_ADDRESS_ReadMask                          0xFFFFFFFC
+#define GCREG_BLOCK4_VPLANE_ADDRESS_WriteMask                         0xFFFFFFFC
+#define GCREG_BLOCK4_VPLANE_ADDRESS_ResetValue                        0x00000000
+
+#define GCREG_BLOCK4_VPLANE_ADDRESS_ADDRESS                               31 : 0
+#define GCREG_BLOCK4_VPLANE_ADDRESS_ADDRESS_End                               30
+#define GCREG_BLOCK4_VPLANE_ADDRESS_ADDRESS_Start                              0
+#define GCREG_BLOCK4_VPLANE_ADDRESS_ADDRESS_Type                             U31
+
+/*******************************************************************************
+** State gcregBlock4StrideV
+*/
+
+/* Stride of the source V plane in bytes. */
+
+#define gcregBlock4VPlaneStrideRegAddrs                                   0x4A34
+#define GCREG_BLOCK4_VPLANE_STRIDE_MSB                                        15
+#define GCREG_BLOCK4_VPLANE_STRIDE_LSB                                         2
+#define GCREG_BLOCK4_VPLANE_STRIDE_BLK                                         0
+#define GCREG_BLOCK4_VPLANE_STRIDE_Count                                       4
+#define GCREG_BLOCK4_VPLANE_STRIDE_FieldMask                          0x0003FFFF
+#define GCREG_BLOCK4_VPLANE_STRIDE_ReadMask                           0x0003FFFC
+#define GCREG_BLOCK4_VPLANE_STRIDE_WriteMask                          0x0003FFFC
+#define GCREG_BLOCK4_VPLANE_STRIDE_ResetValue                         0x00000000
+
+#define GCREG_BLOCK4_VPLANE_STRIDE_STRIDE                                 17 : 0
+#define GCREG_BLOCK4_VPLANE_STRIDE_STRIDE_End                                 17
+#define GCREG_BLOCK4_VPLANE_STRIDE_STRIDE_Start                                0
+#define GCREG_BLOCK4_VPLANE_STRIDE_STRIDE_Type                               U18
+
+/*******************************************************************************
+** State gcregBlock4SrcRotationHeight
+*/
+
+/* 180/270 degree rotation configuration for the Source surface. Height field
+** specifies the height of the surface in pixels.
+*/
+
+#define gcregBlock4SrcRotationHeightRegAddrs                              0x4A38
+#define GCREG_BLOCK4_SRC_ROTATION_HEIGHT_MSB                                  15
+#define GCREG_BLOCK4_SRC_ROTATION_HEIGHT_LSB                                   2
+#define GCREG_BLOCK4_SRC_ROTATION_HEIGHT_BLK                                   0
+#define GCREG_BLOCK4_SRC_ROTATION_HEIGHT_Count                                 4
+#define GCREG_BLOCK4_SRC_ROTATION_HEIGHT_FieldMask                    0x0000FFFF
+#define GCREG_BLOCK4_SRC_ROTATION_HEIGHT_ReadMask                     0x0000FFFF
+#define GCREG_BLOCK4_SRC_ROTATION_HEIGHT_WriteMask                    0x0000FFFF
+#define GCREG_BLOCK4_SRC_ROTATION_HEIGHT_ResetValue                   0x00000000
+
+#define GCREG_BLOCK4_SRC_ROTATION_HEIGHT_HEIGHT                           15 : 0
+#define GCREG_BLOCK4_SRC_ROTATION_HEIGHT_HEIGHT_End                           15
+#define GCREG_BLOCK4_SRC_ROTATION_HEIGHT_HEIGHT_Start                          0
+#define GCREG_BLOCK4_SRC_ROTATION_HEIGHT_HEIGHT_Type                         U16
+
+/*******************************************************************************
+** State gcregBlock4RotAngle
+*/
+
+/* 0/90/180/270 degree rotation configuration for the Source surface. Height
+** field specifies the height of the surface in pixels.
+*/
+
+#define gcregBlock4RotAngleRegAddrs                                       0x4A3C
+#define GCREG_BLOCK4_ROT_ANGLE_MSB                                            15
+#define GCREG_BLOCK4_ROT_ANGLE_LSB                                             2
+#define GCREG_BLOCK4_ROT_ANGLE_BLK                                             0
+#define GCREG_BLOCK4_ROT_ANGLE_Count                                           4
+#define GCREG_BLOCK4_ROT_ANGLE_FieldMask                              0x000BB33F
+#define GCREG_BLOCK4_ROT_ANGLE_ReadMask                               0x000BB33F
+#define GCREG_BLOCK4_ROT_ANGLE_WriteMask                              0x000BB33F
+#define GCREG_BLOCK4_ROT_ANGLE_ResetValue                             0x00000000
+
+#define GCREG_BLOCK4_ROT_ANGLE_SRC                                         2 : 0
+#define GCREG_BLOCK4_ROT_ANGLE_SRC_End                                         2
+#define GCREG_BLOCK4_ROT_ANGLE_SRC_Start                                       0
+#define GCREG_BLOCK4_ROT_ANGLE_SRC_Type                                      U03
+#define   GCREG_BLOCK4_ROT_ANGLE_SRC_ROT0                                    0x0
+#define   GCREG_BLOCK4_ROT_ANGLE_SRC_FLIP_X                                  0x1
+#define   GCREG_BLOCK4_ROT_ANGLE_SRC_FLIP_Y                                  0x2
+#define   GCREG_BLOCK4_ROT_ANGLE_SRC_ROT90                                   0x4
+#define   GCREG_BLOCK4_ROT_ANGLE_SRC_ROT180                                  0x5
+#define   GCREG_BLOCK4_ROT_ANGLE_SRC_ROT270                                  0x6
+
+#define GCREG_BLOCK4_ROT_ANGLE_DST                                         5 : 3
+#define GCREG_BLOCK4_ROT_ANGLE_DST_End                                         5
+#define GCREG_BLOCK4_ROT_ANGLE_DST_Start                                       3
+#define GCREG_BLOCK4_ROT_ANGLE_DST_Type                                      U03
+#define   GCREG_BLOCK4_ROT_ANGLE_DST_ROT0                                    0x0
+#define   GCREG_BLOCK4_ROT_ANGLE_DST_FLIP_X                                  0x1
+#define   GCREG_BLOCK4_ROT_ANGLE_DST_FLIP_Y                                  0x2
+#define   GCREG_BLOCK4_ROT_ANGLE_DST_ROT90                                   0x4
+#define   GCREG_BLOCK4_ROT_ANGLE_DST_ROT180                                  0x5
+#define   GCREG_BLOCK4_ROT_ANGLE_DST_ROT270                                  0x6
+
+#define GCREG_BLOCK4_ROT_ANGLE_MASK_SRC                                    8 : 8
+#define GCREG_BLOCK4_ROT_ANGLE_MASK_SRC_End                                    8
+#define GCREG_BLOCK4_ROT_ANGLE_MASK_SRC_Start                                  8
+#define GCREG_BLOCK4_ROT_ANGLE_MASK_SRC_Type                                 U01
+#define   GCREG_BLOCK4_ROT_ANGLE_MASK_SRC_ENABLED                            0x0
+#define   GCREG_BLOCK4_ROT_ANGLE_MASK_SRC_MASKED                             0x1
+
+#define GCREG_BLOCK4_ROT_ANGLE_MASK_DST                                    9 : 9
+#define GCREG_BLOCK4_ROT_ANGLE_MASK_DST_End                                    9
+#define GCREG_BLOCK4_ROT_ANGLE_MASK_DST_Start                                  9
+#define GCREG_BLOCK4_ROT_ANGLE_MASK_DST_Type                                 U01
+#define   GCREG_BLOCK4_ROT_ANGLE_MASK_DST_ENABLED                            0x0
+#define   GCREG_BLOCK4_ROT_ANGLE_MASK_DST_MASKED                             0x1
+
+#define GCREG_BLOCK4_ROT_ANGLE_SRC_MIRROR                                13 : 12
+#define GCREG_BLOCK4_ROT_ANGLE_SRC_MIRROR_End                                 13
+#define GCREG_BLOCK4_ROT_ANGLE_SRC_MIRROR_Start                               12
+#define GCREG_BLOCK4_ROT_ANGLE_SRC_MIRROR_Type                               U02
+#define   GCREG_BLOCK4_ROT_ANGLE_SRC_MIRROR_NONE                             0x0
+#define   GCREG_BLOCK4_ROT_ANGLE_SRC_MIRROR_MIRROR_X                         0x1
+#define   GCREG_BLOCK4_ROT_ANGLE_SRC_MIRROR_MIRROR_Y                         0x2
+#define   GCREG_BLOCK4_ROT_ANGLE_SRC_MIRROR_MIRROR_XY                        0x3
+
+#define GCREG_BLOCK4_ROT_ANGLE_MASK_SRC_MIRROR                           15 : 15
+#define GCREG_BLOCK4_ROT_ANGLE_MASK_SRC_MIRROR_End                            15
+#define GCREG_BLOCK4_ROT_ANGLE_MASK_SRC_MIRROR_Start                          15
+#define GCREG_BLOCK4_ROT_ANGLE_MASK_SRC_MIRROR_Type                          U01
+#define   GCREG_BLOCK4_ROT_ANGLE_MASK_SRC_MIRROR_ENABLED                     0x0
+#define   GCREG_BLOCK4_ROT_ANGLE_MASK_SRC_MIRROR_MASKED                      0x1
+
+#define GCREG_BLOCK4_ROT_ANGLE_DST_MIRROR                                17 : 16
+#define GCREG_BLOCK4_ROT_ANGLE_DST_MIRROR_End                                 17
+#define GCREG_BLOCK4_ROT_ANGLE_DST_MIRROR_Start                               16
+#define GCREG_BLOCK4_ROT_ANGLE_DST_MIRROR_Type                               U02
+#define   GCREG_BLOCK4_ROT_ANGLE_DST_MIRROR_NONE                             0x0
+#define   GCREG_BLOCK4_ROT_ANGLE_DST_MIRROR_MIRROR_X                         0x1
+#define   GCREG_BLOCK4_ROT_ANGLE_DST_MIRROR_MIRROR_Y                         0x2
+#define   GCREG_BLOCK4_ROT_ANGLE_DST_MIRROR_MIRROR_XY                        0x3
+
+#define GCREG_BLOCK4_ROT_ANGLE_MASK_DST_MIRROR                           19 : 19
+#define GCREG_BLOCK4_ROT_ANGLE_MASK_DST_MIRROR_End                            19
+#define GCREG_BLOCK4_ROT_ANGLE_MASK_DST_MIRROR_Start                          19
+#define GCREG_BLOCK4_ROT_ANGLE_MASK_DST_MIRROR_Type                          U01
+#define   GCREG_BLOCK4_ROT_ANGLE_MASK_DST_MIRROR_ENABLED                     0x0
+#define   GCREG_BLOCK4_ROT_ANGLE_MASK_DST_MIRROR_MASKED                      0x1
+
+/*******************************************************************************
+** State gcregBlock4GlobalSrcColor
+*/
+
+/* Defines the global source color and alpha values. */
+
+#define gcregBlock4GlobalSrcColorRegAddrs                                 0x4A40
+#define GCREG_BLOCK4_GLOBAL_SRC_COLOR_MSB                                     15
+#define GCREG_BLOCK4_GLOBAL_SRC_COLOR_LSB                                      2
+#define GCREG_BLOCK4_GLOBAL_SRC_COLOR_BLK                                      0
+#define GCREG_BLOCK4_GLOBAL_SRC_COLOR_Count                                    4
+#define GCREG_BLOCK4_GLOBAL_SRC_COLOR_FieldMask                       0xFFFFFFFF
+#define GCREG_BLOCK4_GLOBAL_SRC_COLOR_ReadMask                        0xFFFFFFFF
+#define GCREG_BLOCK4_GLOBAL_SRC_COLOR_WriteMask                       0xFFFFFFFF
+#define GCREG_BLOCK4_GLOBAL_SRC_COLOR_ResetValue                      0x00000000
+
+#define GCREG_BLOCK4_GLOBAL_SRC_COLOR_ALPHA                              31 : 24
+#define GCREG_BLOCK4_GLOBAL_SRC_COLOR_ALPHA_End                               31
+#define GCREG_BLOCK4_GLOBAL_SRC_COLOR_ALPHA_Start                             24
+#define GCREG_BLOCK4_GLOBAL_SRC_COLOR_ALPHA_Type                             U08
+
+#define GCREG_BLOCK4_GLOBAL_SRC_COLOR_RED                                23 : 16
+#define GCREG_BLOCK4_GLOBAL_SRC_COLOR_RED_End                                 23
+#define GCREG_BLOCK4_GLOBAL_SRC_COLOR_RED_Start                               16
+#define GCREG_BLOCK4_GLOBAL_SRC_COLOR_RED_Type                               U08
+
+#define GCREG_BLOCK4_GLOBAL_SRC_COLOR_GREEN                               15 : 8
+#define GCREG_BLOCK4_GLOBAL_SRC_COLOR_GREEN_End                               15
+#define GCREG_BLOCK4_GLOBAL_SRC_COLOR_GREEN_Start                              8
+#define GCREG_BLOCK4_GLOBAL_SRC_COLOR_GREEN_Type                             U08
+
+#define GCREG_BLOCK4_GLOBAL_SRC_COLOR_BLUE                                 7 : 0
+#define GCREG_BLOCK4_GLOBAL_SRC_COLOR_BLUE_End                                 7
+#define GCREG_BLOCK4_GLOBAL_SRC_COLOR_BLUE_Start                               0
+#define GCREG_BLOCK4_GLOBAL_SRC_COLOR_BLUE_Type                              U08
+
+/*******************************************************************************
+** State gcregBlock4GlobalDestColor
+*/
+
+/* Defines the global destination color and alpha values. */
+
+#define gcregBlock4GlobalDestColorRegAddrs                                0x4A44
+#define GCREG_BLOCK4_GLOBAL_DEST_COLOR_MSB                                    15
+#define GCREG_BLOCK4_GLOBAL_DEST_COLOR_LSB                                     2
+#define GCREG_BLOCK4_GLOBAL_DEST_COLOR_BLK                                     0
+#define GCREG_BLOCK4_GLOBAL_DEST_COLOR_Count                                   4
+#define GCREG_BLOCK4_GLOBAL_DEST_COLOR_FieldMask                      0xFFFFFFFF
+#define GCREG_BLOCK4_GLOBAL_DEST_COLOR_ReadMask                       0xFFFFFFFF
+#define GCREG_BLOCK4_GLOBAL_DEST_COLOR_WriteMask                      0xFFFFFFFF
+#define GCREG_BLOCK4_GLOBAL_DEST_COLOR_ResetValue                     0x00000000
+
+#define GCREG_BLOCK4_GLOBAL_DEST_COLOR_ALPHA                             31 : 24
+#define GCREG_BLOCK4_GLOBAL_DEST_COLOR_ALPHA_End                              31
+#define GCREG_BLOCK4_GLOBAL_DEST_COLOR_ALPHA_Start                            24
+#define GCREG_BLOCK4_GLOBAL_DEST_COLOR_ALPHA_Type                            U08
+
+#define GCREG_BLOCK4_GLOBAL_DEST_COLOR_RED                               23 : 16
+#define GCREG_BLOCK4_GLOBAL_DEST_COLOR_RED_End                                23
+#define GCREG_BLOCK4_GLOBAL_DEST_COLOR_RED_Start                              16
+#define GCREG_BLOCK4_GLOBAL_DEST_COLOR_RED_Type                              U08
+
+#define GCREG_BLOCK4_GLOBAL_DEST_COLOR_GREEN                              15 : 8
+#define GCREG_BLOCK4_GLOBAL_DEST_COLOR_GREEN_End                              15
+#define GCREG_BLOCK4_GLOBAL_DEST_COLOR_GREEN_Start                             8
+#define GCREG_BLOCK4_GLOBAL_DEST_COLOR_GREEN_Type                            U08
+
+#define GCREG_BLOCK4_GLOBAL_DEST_COLOR_BLUE                                7 : 0
+#define GCREG_BLOCK4_GLOBAL_DEST_COLOR_BLUE_End                                7
+#define GCREG_BLOCK4_GLOBAL_DEST_COLOR_BLUE_Start                              0
+#define GCREG_BLOCK4_GLOBAL_DEST_COLOR_BLUE_Type                             U08
+
+/*******************************************************************************
+** State gcregBlock4ColorMultiplyModes
+*/
+
+/* Color modes to multiply Source or Destination pixel color by alpha
+** channel. Alpha can be from global color source or current pixel.
+*/
+
+#define gcregBlock4ColorMultiplyModesRegAddrs                             0x4A48
+#define GCREG_BLOCK4_COLOR_MULTIPLY_MODES_MSB                                 15
+#define GCREG_BLOCK4_COLOR_MULTIPLY_MODES_LSB                                  2
+#define GCREG_BLOCK4_COLOR_MULTIPLY_MODES_BLK                                  0
+#define GCREG_BLOCK4_COLOR_MULTIPLY_MODES_Count                                4
+#define GCREG_BLOCK4_COLOR_MULTIPLY_MODES_FieldMask                   0x00100311
+#define GCREG_BLOCK4_COLOR_MULTIPLY_MODES_ReadMask                    0x00100311
+#define GCREG_BLOCK4_COLOR_MULTIPLY_MODES_WriteMask                   0x00100311
+#define GCREG_BLOCK4_COLOR_MULTIPLY_MODES_ResetValue                  0x00000000
+
+#define GCREG_BLOCK4_COLOR_MULTIPLY_MODES_SRC_PREMULTIPLY                  0 : 0
+#define GCREG_BLOCK4_COLOR_MULTIPLY_MODES_SRC_PREMULTIPLY_End                  0
+#define GCREG_BLOCK4_COLOR_MULTIPLY_MODES_SRC_PREMULTIPLY_Start                0
+#define GCREG_BLOCK4_COLOR_MULTIPLY_MODES_SRC_PREMULTIPLY_Type               U01
+#define   GCREG_BLOCK4_COLOR_MULTIPLY_MODES_SRC_PREMULTIPLY_DISABLE          0x0
+#define   GCREG_BLOCK4_COLOR_MULTIPLY_MODES_SRC_PREMULTIPLY_ENABLE           0x1
+
+#define GCREG_BLOCK4_COLOR_MULTIPLY_MODES_DST_PREMULTIPLY                  4 : 4
+#define GCREG_BLOCK4_COLOR_MULTIPLY_MODES_DST_PREMULTIPLY_End                  4
+#define GCREG_BLOCK4_COLOR_MULTIPLY_MODES_DST_PREMULTIPLY_Start                4
+#define GCREG_BLOCK4_COLOR_MULTIPLY_MODES_DST_PREMULTIPLY_Type               U01
+#define   GCREG_BLOCK4_COLOR_MULTIPLY_MODES_DST_PREMULTIPLY_DISABLE          0x0
+#define   GCREG_BLOCK4_COLOR_MULTIPLY_MODES_DST_PREMULTIPLY_ENABLE           0x1
+
+#define GCREG_BLOCK4_COLOR_MULTIPLY_MODES_SRC_GLOBAL_PREMULTIPLY           9 : 8
+#define GCREG_BLOCK4_COLOR_MULTIPLY_MODES_SRC_GLOBAL_PREMULTIPLY_End           9
+#define GCREG_BLOCK4_COLOR_MULTIPLY_MODES_SRC_GLOBAL_PREMULTIPLY_Start         8
+#define GCREG_BLOCK4_COLOR_MULTIPLY_MODES_SRC_GLOBAL_PREMULTIPLY_Type        U02
+#define   GCREG_BLOCK4_COLOR_MULTIPLY_MODES_SRC_GLOBAL_PREMULTIPLY_DISABLE   0x0
+#define   GCREG_BLOCK4_COLOR_MULTIPLY_MODES_SRC_GLOBAL_PREMULTIPLY_ALPHA     0x1
+#define   GCREG_BLOCK4_COLOR_MULTIPLY_MODES_SRC_GLOBAL_PREMULTIPLY_COLOR     0x2
+
+#define GCREG_BLOCK4_COLOR_MULTIPLY_MODES_DST_DEMULTIPLY                 20 : 20
+#define GCREG_BLOCK4_COLOR_MULTIPLY_MODES_DST_DEMULTIPLY_End                  20
+#define GCREG_BLOCK4_COLOR_MULTIPLY_MODES_DST_DEMULTIPLY_Start                20
+#define GCREG_BLOCK4_COLOR_MULTIPLY_MODES_DST_DEMULTIPLY_Type                U01
+#define   GCREG_BLOCK4_COLOR_MULTIPLY_MODES_DST_DEMULTIPLY_DISABLE           0x0
+#define   GCREG_BLOCK4_COLOR_MULTIPLY_MODES_DST_DEMULTIPLY_ENABLE            0x1
+
+/*******************************************************************************
+** State gcregBlock4Transparency
+*/
+
+#define gcregBlock4TransparencyRegAddrs                                   0x4A4C
+#define GCREG_BLOCK4_TRANSPARENCY_MSB                                         15
+#define GCREG_BLOCK4_TRANSPARENCY_LSB                                          2
+#define GCREG_BLOCK4_TRANSPARENCY_BLK                                          0
+#define GCREG_BLOCK4_TRANSPARENCY_Count                                        4
+#define GCREG_BLOCK4_TRANSPARENCY_FieldMask                           0xB3331333
+#define GCREG_BLOCK4_TRANSPARENCY_ReadMask                            0xB3331333
+#define GCREG_BLOCK4_TRANSPARENCY_WriteMask                           0xB3331333
+#define GCREG_BLOCK4_TRANSPARENCY_ResetValue                          0x00000000
+
+/* Source transparency mode. */
+#define GCREG_BLOCK4_TRANSPARENCY_SOURCE                                   1 : 0
+#define GCREG_BLOCK4_TRANSPARENCY_SOURCE_End                                   1
+#define GCREG_BLOCK4_TRANSPARENCY_SOURCE_Start                                 0
+#define GCREG_BLOCK4_TRANSPARENCY_SOURCE_Type                                U02
+#define   GCREG_BLOCK4_TRANSPARENCY_SOURCE_OPAQUE                            0x0
+#define   GCREG_BLOCK4_TRANSPARENCY_SOURCE_MASK                              0x1
+#define   GCREG_BLOCK4_TRANSPARENCY_SOURCE_KEY                               0x2
+
+/* Pattern transparency mode. KEY transparency mode is reserved. */
+#define GCREG_BLOCK4_TRANSPARENCY_PATTERN                                  5 : 4
+#define GCREG_BLOCK4_TRANSPARENCY_PATTERN_End                                  5
+#define GCREG_BLOCK4_TRANSPARENCY_PATTERN_Start                                4
+#define GCREG_BLOCK4_TRANSPARENCY_PATTERN_Type                               U02
+#define   GCREG_BLOCK4_TRANSPARENCY_PATTERN_OPAQUE                           0x0
+#define   GCREG_BLOCK4_TRANSPARENCY_PATTERN_MASK                             0x1
+#define   GCREG_BLOCK4_TRANSPARENCY_PATTERN_KEY                              0x2
+
+/* Destination transparency mode. MASK transparency mode is reserved. */
+#define GCREG_BLOCK4_TRANSPARENCY_DESTINATION                              9 : 8
+#define GCREG_BLOCK4_TRANSPARENCY_DESTINATION_End                              9
+#define GCREG_BLOCK4_TRANSPARENCY_DESTINATION_Start                            8
+#define GCREG_BLOCK4_TRANSPARENCY_DESTINATION_Type                           U02
+#define   GCREG_BLOCK4_TRANSPARENCY_DESTINATION_OPAQUE                       0x0
+#define   GCREG_BLOCK4_TRANSPARENCY_DESTINATION_MASK                         0x1
+#define   GCREG_BLOCK4_TRANSPARENCY_DESTINATION_KEY                          0x2
+
+/* Mask field for Source/Pattern/Destination fields. */
+#define GCREG_BLOCK4_TRANSPARENCY_MASK_TRANSPARENCY                      12 : 12
+#define GCREG_BLOCK4_TRANSPARENCY_MASK_TRANSPARENCY_End                       12
+#define GCREG_BLOCK4_TRANSPARENCY_MASK_TRANSPARENCY_Start                     12
+#define GCREG_BLOCK4_TRANSPARENCY_MASK_TRANSPARENCY_Type                     U01
+#define   GCREG_BLOCK4_TRANSPARENCY_MASK_TRANSPARENCY_ENABLED                0x0
+#define   GCREG_BLOCK4_TRANSPARENCY_MASK_TRANSPARENCY_MASKED                 0x1
+
+/* Source usage override. */
+#define GCREG_BLOCK4_TRANSPARENCY_USE_SRC_OVERRIDE                       17 : 16
+#define GCREG_BLOCK4_TRANSPARENCY_USE_SRC_OVERRIDE_End                        17
+#define GCREG_BLOCK4_TRANSPARENCY_USE_SRC_OVERRIDE_Start                      16
+#define GCREG_BLOCK4_TRANSPARENCY_USE_SRC_OVERRIDE_Type                      U02
+#define   GCREG_BLOCK4_TRANSPARENCY_USE_SRC_OVERRIDE_DEFAULT                 0x0
+#define   GCREG_BLOCK4_TRANSPARENCY_USE_SRC_OVERRIDE_USE_ENABLE              0x1
+#define   GCREG_BLOCK4_TRANSPARENCY_USE_SRC_OVERRIDE_USE_DISABLE             0x2
+
+/* Pattern usage override. */
+#define GCREG_BLOCK4_TRANSPARENCY_USE_PAT_OVERRIDE                       21 : 20
+#define GCREG_BLOCK4_TRANSPARENCY_USE_PAT_OVERRIDE_End                        21
+#define GCREG_BLOCK4_TRANSPARENCY_USE_PAT_OVERRIDE_Start                      20
+#define GCREG_BLOCK4_TRANSPARENCY_USE_PAT_OVERRIDE_Type                      U02
+#define   GCREG_BLOCK4_TRANSPARENCY_USE_PAT_OVERRIDE_DEFAULT                 0x0
+#define   GCREG_BLOCK4_TRANSPARENCY_USE_PAT_OVERRIDE_USE_ENABLE              0x1
+#define   GCREG_BLOCK4_TRANSPARENCY_USE_PAT_OVERRIDE_USE_DISABLE             0x2
+
+/* Destination usage override. */
+#define GCREG_BLOCK4_TRANSPARENCY_USE_DST_OVERRIDE                       25 : 24
+#define GCREG_BLOCK4_TRANSPARENCY_USE_DST_OVERRIDE_End                        25
+#define GCREG_BLOCK4_TRANSPARENCY_USE_DST_OVERRIDE_Start                      24
+#define GCREG_BLOCK4_TRANSPARENCY_USE_DST_OVERRIDE_Type                      U02
+#define   GCREG_BLOCK4_TRANSPARENCY_USE_DST_OVERRIDE_DEFAULT                 0x0
+#define   GCREG_BLOCK4_TRANSPARENCY_USE_DST_OVERRIDE_USE_ENABLE              0x1
+#define   GCREG_BLOCK4_TRANSPARENCY_USE_DST_OVERRIDE_USE_DISABLE             0x2
+
+/* 2D resource usage override mask field. */
+#define GCREG_BLOCK4_TRANSPARENCY_MASK_RESOURCE_OVERRIDE                 28 : 28
+#define GCREG_BLOCK4_TRANSPARENCY_MASK_RESOURCE_OVERRIDE_End                  28
+#define GCREG_BLOCK4_TRANSPARENCY_MASK_RESOURCE_OVERRIDE_Start                28
+#define GCREG_BLOCK4_TRANSPARENCY_MASK_RESOURCE_OVERRIDE_Type                U01
+#define   GCREG_BLOCK4_TRANSPARENCY_MASK_RESOURCE_OVERRIDE_ENABLED           0x0
+#define   GCREG_BLOCK4_TRANSPARENCY_MASK_RESOURCE_OVERRIDE_MASKED            0x1
+
+/* DFB Color Key. */
+#define GCREG_BLOCK4_TRANSPARENCY_DFB_COLOR_KEY                          29 : 29
+#define GCREG_BLOCK4_TRANSPARENCY_DFB_COLOR_KEY_End                           29
+#define GCREG_BLOCK4_TRANSPARENCY_DFB_COLOR_KEY_Start                         29
+#define GCREG_BLOCK4_TRANSPARENCY_DFB_COLOR_KEY_Type                         U01
+#define   GCREG_BLOCK4_TRANSPARENCY_DFB_COLOR_KEY_DISABLED                   0x0
+#define   GCREG_BLOCK4_TRANSPARENCY_DFB_COLOR_KEY_ENABLED                    0x1
+
+#define GCREG_BLOCK4_TRANSPARENCY_MASK_DFB_COLOR_KEY                     31 : 31
+#define GCREG_BLOCK4_TRANSPARENCY_MASK_DFB_COLOR_KEY_End                      31
+#define GCREG_BLOCK4_TRANSPARENCY_MASK_DFB_COLOR_KEY_Start                    31
+#define GCREG_BLOCK4_TRANSPARENCY_MASK_DFB_COLOR_KEY_Type                    U01
+#define   GCREG_BLOCK4_TRANSPARENCY_MASK_DFB_COLOR_KEY_ENABLED               0x0
+#define   GCREG_BLOCK4_TRANSPARENCY_MASK_DFB_COLOR_KEY_MASKED                0x1
+
+/*******************************************************************************
+** State gcregBlock4Control
+*/
+
+/* General purpose control register. */
+
+#define gcregBlock4PEControlRegAddrs                                      0x4A50
+#define GCREG_BLOCK4_PE_CONTROL_MSB                                           15
+#define GCREG_BLOCK4_PE_CONTROL_LSB                                            2
+#define GCREG_BLOCK4_PE_CONTROL_BLK                                            0
+#define GCREG_BLOCK4_PE_CONTROL_Count                                          4
+#define GCREG_BLOCK4_PE_CONTROL_FieldMask                             0x00000999
+#define GCREG_BLOCK4_PE_CONTROL_ReadMask                              0x00000999
+#define GCREG_BLOCK4_PE_CONTROL_WriteMask                             0x00000999
+#define GCREG_BLOCK4_PE_CONTROL_ResetValue                            0x00000000
+
+#define GCREG_BLOCK4_PE_CONTROL_YUV                                        0 : 0
+#define GCREG_BLOCK4_PE_CONTROL_YUV_End                                        0
+#define GCREG_BLOCK4_PE_CONTROL_YUV_Start                                      0
+#define GCREG_BLOCK4_PE_CONTROL_YUV_Type                                     U01
+#define   GCREG_BLOCK4_PE_CONTROL_YUV_601                                    0x0
+#define   GCREG_BLOCK4_PE_CONTROL_YUV_709                                    0x1
+
+#define GCREG_BLOCK4_PE_CONTROL_MASK_YUV                                   3 : 3
+#define GCREG_BLOCK4_PE_CONTROL_MASK_YUV_End                                   3
+#define GCREG_BLOCK4_PE_CONTROL_MASK_YUV_Start                                 3
+#define GCREG_BLOCK4_PE_CONTROL_MASK_YUV_Type                                U01
+#define   GCREG_BLOCK4_PE_CONTROL_MASK_YUV_ENABLED                           0x0
+#define   GCREG_BLOCK4_PE_CONTROL_MASK_YUV_MASKED                            0x1
+
+#define GCREG_BLOCK4_PE_CONTROL_UV_SWIZZLE                                 4 : 4
+#define GCREG_BLOCK4_PE_CONTROL_UV_SWIZZLE_End                                 4
+#define GCREG_BLOCK4_PE_CONTROL_UV_SWIZZLE_Start                               4
+#define GCREG_BLOCK4_PE_CONTROL_UV_SWIZZLE_Type                              U01
+#define   GCREG_BLOCK4_PE_CONTROL_UV_SWIZZLE_UV                              0x0
+#define   GCREG_BLOCK4_PE_CONTROL_UV_SWIZZLE_VU                              0x1
+
+#define GCREG_BLOCK4_PE_CONTROL_MASK_UV_SWIZZLE                            7 : 7
+#define GCREG_BLOCK4_PE_CONTROL_MASK_UV_SWIZZLE_End                            7
+#define GCREG_BLOCK4_PE_CONTROL_MASK_UV_SWIZZLE_Start                          7
+#define GCREG_BLOCK4_PE_CONTROL_MASK_UV_SWIZZLE_Type                         U01
+#define   GCREG_BLOCK4_PE_CONTROL_MASK_UV_SWIZZLE_ENABLED                    0x0
+#define   GCREG_BLOCK4_PE_CONTROL_MASK_UV_SWIZZLE_MASKED                     0x1
+
+/* YUV to RGB convert enable */
+#define GCREG_BLOCK4_PE_CONTROL_YUVRGB                                     8 : 8
+#define GCREG_BLOCK4_PE_CONTROL_YUVRGB_End                                     8
+#define GCREG_BLOCK4_PE_CONTROL_YUVRGB_Start                                   8
+#define GCREG_BLOCK4_PE_CONTROL_YUVRGB_Type                                  U01
+#define   GCREG_BLOCK4_PE_CONTROL_YUVRGB_DISABLED                            0x0
+#define   GCREG_BLOCK4_PE_CONTROL_YUVRGB_ENABLED                             0x1
+
+#define GCREG_BLOCK4_PE_CONTROL_MASK_YUVRGB                              11 : 11
+#define GCREG_BLOCK4_PE_CONTROL_MASK_YUVRGB_End                               11
+#define GCREG_BLOCK4_PE_CONTROL_MASK_YUVRGB_Start                             11
+#define GCREG_BLOCK4_PE_CONTROL_MASK_YUVRGB_Type                             U01
+#define   GCREG_BLOCK4_PE_CONTROL_MASK_YUVRGB_ENABLED                        0x0
+#define   GCREG_BLOCK4_PE_CONTROL_MASK_YUVRGB_MASKED                         0x1
+
+/*******************************************************************************
+** State gcregBlock4SrcColorKeyHigh
+*/
+
+/* Defines the source transparency color in source format. */
+
+#define gcregBlock4SrcColorKeyHighRegAddrs                                0x4A54
+#define GCREG_BLOCK4_SRC_COLOR_KEY_HIGH_MSB                                   15
+#define GCREG_BLOCK4_SRC_COLOR_KEY_HIGH_LSB                                    2
+#define GCREG_BLOCK4_SRC_COLOR_KEY_HIGH_BLK                                    0
+#define GCREG_BLOCK4_SRC_COLOR_KEY_HIGH_Count                                  4
+#define GCREG_BLOCK4_SRC_COLOR_KEY_HIGH_FieldMask                     0xFFFFFFFF
+#define GCREG_BLOCK4_SRC_COLOR_KEY_HIGH_ReadMask                      0xFFFFFFFF
+#define GCREG_BLOCK4_SRC_COLOR_KEY_HIGH_WriteMask                     0xFFFFFFFF
+#define GCREG_BLOCK4_SRC_COLOR_KEY_HIGH_ResetValue                    0x00000000
+
+#define GCREG_BLOCK4_SRC_COLOR_KEY_HIGH_ALPHA                            31 : 24
+#define GCREG_BLOCK4_SRC_COLOR_KEY_HIGH_ALPHA_End                             31
+#define GCREG_BLOCK4_SRC_COLOR_KEY_HIGH_ALPHA_Start                           24
+#define GCREG_BLOCK4_SRC_COLOR_KEY_HIGH_ALPHA_Type                           U08
+
+#define GCREG_BLOCK4_SRC_COLOR_KEY_HIGH_RED                              23 : 16
+#define GCREG_BLOCK4_SRC_COLOR_KEY_HIGH_RED_End                               23
+#define GCREG_BLOCK4_SRC_COLOR_KEY_HIGH_RED_Start                             16
+#define GCREG_BLOCK4_SRC_COLOR_KEY_HIGH_RED_Type                             U08
+
+#define GCREG_BLOCK4_SRC_COLOR_KEY_HIGH_GREEN                             15 : 8
+#define GCREG_BLOCK4_SRC_COLOR_KEY_HIGH_GREEN_End                             15
+#define GCREG_BLOCK4_SRC_COLOR_KEY_HIGH_GREEN_Start                            8
+#define GCREG_BLOCK4_SRC_COLOR_KEY_HIGH_GREEN_Type                           U08
+
+#define GCREG_BLOCK4_SRC_COLOR_KEY_HIGH_BLUE                               7 : 0
+#define GCREG_BLOCK4_SRC_COLOR_KEY_HIGH_BLUE_End                               7
+#define GCREG_BLOCK4_SRC_COLOR_KEY_HIGH_BLUE_Start                             0
+#define GCREG_BLOCK4_SRC_COLOR_KEY_HIGH_BLUE_Type                            U08
+
+/*******************************************************************************
+** State gcregBlock4SrcExConfig
+*/
+
+#define gcregBlock4SrcExConfigRegAddrs                                    0x4A58
+#define GCREG_BLOCK4_SRC_EX_CONFIG_MSB                                        15
+#define GCREG_BLOCK4_SRC_EX_CONFIG_LSB                                         2
+#define GCREG_BLOCK4_SRC_EX_CONFIG_BLK                                         0
+#define GCREG_BLOCK4_SRC_EX_CONFIG_Count                                       4
+#define GCREG_BLOCK4_SRC_EX_CONFIG_FieldMask                          0x00000109
+#define GCREG_BLOCK4_SRC_EX_CONFIG_ReadMask                           0x00000109
+#define GCREG_BLOCK4_SRC_EX_CONFIG_WriteMask                          0x00000109
+#define GCREG_BLOCK4_SRC_EX_CONFIG_ResetValue                         0x00000000
+
+/* Source multi tiled address computation control. */
+#define GCREG_BLOCK4_SRC_EX_CONFIG_MULTI_TILED                             0 : 0
+#define GCREG_BLOCK4_SRC_EX_CONFIG_MULTI_TILED_End                             0
+#define GCREG_BLOCK4_SRC_EX_CONFIG_MULTI_TILED_Start                           0
+#define GCREG_BLOCK4_SRC_EX_CONFIG_MULTI_TILED_Type                          U01
+#define   GCREG_BLOCK4_SRC_EX_CONFIG_MULTI_TILED_DISABLED                    0x0
+#define   GCREG_BLOCK4_SRC_EX_CONFIG_MULTI_TILED_ENABLED                     0x1
+
+/* Source super tiled address computation control. */
+#define GCREG_BLOCK4_SRC_EX_CONFIG_SUPER_TILED                             3 : 3
+#define GCREG_BLOCK4_SRC_EX_CONFIG_SUPER_TILED_End                             3
+#define GCREG_BLOCK4_SRC_EX_CONFIG_SUPER_TILED_Start                           3
+#define GCREG_BLOCK4_SRC_EX_CONFIG_SUPER_TILED_Type                          U01
+#define   GCREG_BLOCK4_SRC_EX_CONFIG_SUPER_TILED_DISABLED                    0x0
+#define   GCREG_BLOCK4_SRC_EX_CONFIG_SUPER_TILED_ENABLED                     0x1
+
+/* Source super tiled address computation control. */
+#define GCREG_BLOCK4_SRC_EX_CONFIG_MINOR_TILED                             8 : 8
+#define GCREG_BLOCK4_SRC_EX_CONFIG_MINOR_TILED_End                             8
+#define GCREG_BLOCK4_SRC_EX_CONFIG_MINOR_TILED_Start                           8
+#define GCREG_BLOCK4_SRC_EX_CONFIG_MINOR_TILED_Type                          U01
+#define   GCREG_BLOCK4_SRC_EX_CONFIG_MINOR_TILED_DISABLED                    0x0
+#define   GCREG_BLOCK4_SRC_EX_CONFIG_MINOR_TILED_ENABLED                     0x1
+
+/* Source CacheMode. */
+#define GCREG_BLOCK4_SRC_EX_CONFIG_CACHE_MODE                            12 : 12
+#define GCREG_BLOCK4_SRC_EX_CONFIG_CACHE_MODE_End                             12
+#define GCREG_BLOCK4_SRC_EX_CONFIG_CACHE_MODE_Start                           12
+#define GCREG_BLOCK4_SRC_EX_CONFIG_CACHE_MODE_Type                           U01
+#define   GCREG_BLOCK4_SRC_EX_CONFIG_CACHE_MODE_DISABLED                     0x0
+#define   GCREG_BLOCK4_SRC_EX_CONFIG_CACHE_MODE_ENABLED                      0x1
+
+/*******************************************************************************
+** State gcregBlock4SrcExAddress
+*/
+
+/* 32-bit aligned base address of the source extra surface. */
+
+#define gcregBlock4SrcExAddressRegAddrs                                   0x4A5C
+#define GCREG_BLOCK4_SRC_EX_ADDRESS_MSB                                       15
+#define GCREG_BLOCK4_SRC_EX_ADDRESS_LSB                                        2
+#define GCREG_BLOCK4_SRC_EX_ADDRESS_BLK                                        0
+#define GCREG_BLOCK4_SRC_EX_ADDRESS_Count                                      4
+#define GCREG_BLOCK4_SRC_EX_ADDRESS_FieldMask                         0xFFFFFFFF
+#define GCREG_BLOCK4_SRC_EX_ADDRESS_ReadMask                          0xFFFFFFFC
+#define GCREG_BLOCK4_SRC_EX_ADDRESS_WriteMask                         0xFFFFFFFC
+#define GCREG_BLOCK4_SRC_EX_ADDRESS_ResetValue                        0x00000000
+
+#define GCREG_BLOCK4_SRC_EX_ADDRESS_ADDRESS                               31 : 0
+#define GCREG_BLOCK4_SRC_EX_ADDRESS_ADDRESS_End                               30
+#define GCREG_BLOCK4_SRC_EX_ADDRESS_ADDRESS_Start                              0
+#define GCREG_BLOCK4_SRC_EX_ADDRESS_ADDRESS_Type                             U31
+
+/*******************************************************************************
+** State gcregBlock8SrcAddressEx
+*/
+
+/* 32-bit aligned base address of the source surface. */
+
+#define gcregBlock8SrcAddressRegAddrs                                     0x4A80
+#define GCREG_BLOCK8_SRC_ADDRESS_MSB                                          15
+#define GCREG_BLOCK8_SRC_ADDRESS_LSB                                           3
+#define GCREG_BLOCK8_SRC_ADDRESS_BLK                                           0
+#define GCREG_BLOCK8_SRC_ADDRESS_Count                                         8
+#define GCREG_BLOCK8_SRC_ADDRESS_FieldMask                            0xFFFFFFFF
+#define GCREG_BLOCK8_SRC_ADDRESS_ReadMask                             0xFFFFFFFC
+#define GCREG_BLOCK8_SRC_ADDRESS_WriteMask                            0xFFFFFFFC
+#define GCREG_BLOCK8_SRC_ADDRESS_ResetValue                           0x00000000
+
+#define GCREG_BLOCK8_SRC_ADDRESS_ADDRESS                                  31 : 0
+#define GCREG_BLOCK8_SRC_ADDRESS_ADDRESS_End                                  30
+#define GCREG_BLOCK8_SRC_ADDRESS_ADDRESS_Start                                 0
+#define GCREG_BLOCK8_SRC_ADDRESS_ADDRESS_Type                                U31
+
+/*******************************************************************************
+** State gcregBlock8SrcStride
+*/
+
+/* Stride of the source surface in bytes. To calculate the stride multiply
+** the surface width in pixels by the number of  bytes per pixel.
+*/
+
+#define gcregBlock8SrcStrideRegAddrs                                      0x4A88
+#define GCREG_BLOCK8_SRC_STRIDE_MSB                                           15
+#define GCREG_BLOCK8_SRC_STRIDE_LSB                                            3
+#define GCREG_BLOCK8_SRC_STRIDE_BLK                                            0
+#define GCREG_BLOCK8_SRC_STRIDE_Count                                          8
+#define GCREG_BLOCK8_SRC_STRIDE_FieldMask                             0x0003FFFF
+#define GCREG_BLOCK8_SRC_STRIDE_ReadMask                              0x0003FFFC
+#define GCREG_BLOCK8_SRC_STRIDE_WriteMask                             0x0003FFFC
+#define GCREG_BLOCK8_SRC_STRIDE_ResetValue                            0x00000000
+
+#define GCREG_BLOCK8_SRC_STRIDE_STRIDE                                    17 : 0
+#define GCREG_BLOCK8_SRC_STRIDE_STRIDE_End                                    17
+#define GCREG_BLOCK8_SRC_STRIDE_STRIDE_Start                                   0
+#define GCREG_BLOCK8_SRC_STRIDE_STRIDE_Type                                  U18
+
+/*******************************************************************************
+** State gcregBlock8SrcRotationConfig
+*/
+
+/* 90 degree rotation configuration for the source surface. Width field
+** specifies the width of the surface in pixels.
+*/
+
+#define gcregBlock8SrcRotationConfigRegAddrs                              0x4A90
+#define GCREG_BLOCK8_SRC_ROTATION_CONFIG_MSB                                  15
+#define GCREG_BLOCK8_SRC_ROTATION_CONFIG_LSB                                   3
+#define GCREG_BLOCK8_SRC_ROTATION_CONFIG_BLK                                   0
+#define GCREG_BLOCK8_SRC_ROTATION_CONFIG_Count                                 8
+#define GCREG_BLOCK8_SRC_ROTATION_CONFIG_FieldMask                    0x0001FFFF
+#define GCREG_BLOCK8_SRC_ROTATION_CONFIG_ReadMask                     0x0001FFFF
+#define GCREG_BLOCK8_SRC_ROTATION_CONFIG_WriteMask                    0x0001FFFF
+#define GCREG_BLOCK8_SRC_ROTATION_CONFIG_ResetValue                   0x00000000
+
+#define GCREG_BLOCK8_SRC_ROTATION_CONFIG_WIDTH                            15 : 0
+#define GCREG_BLOCK8_SRC_ROTATION_CONFIG_WIDTH_End                            15
+#define GCREG_BLOCK8_SRC_ROTATION_CONFIG_WIDTH_Start                           0
+#define GCREG_BLOCK8_SRC_ROTATION_CONFIG_WIDTH_Type                          U16
+
+#define GCREG_BLOCK8_SRC_ROTATION_CONFIG_ROTATION                        16 : 16
+#define GCREG_BLOCK8_SRC_ROTATION_CONFIG_ROTATION_End                         16
+#define GCREG_BLOCK8_SRC_ROTATION_CONFIG_ROTATION_Start                       16
+#define GCREG_BLOCK8_SRC_ROTATION_CONFIG_ROTATION_Type                       U01
+#define   GCREG_BLOCK8_SRC_ROTATION_CONFIG_ROTATION_NORMAL                   0x0
+#define   GCREG_BLOCK8_SRC_ROTATION_CONFIG_ROTATION_ROTATED                  0x1
+
+/*******************************************************************************
+** State gcregBlock8SrcConfig
+*/
+
+/* Source surface configuration register. */
+
+#define gcregBlock8SrcConfigRegAddrs                                      0x4A98
+#define GCREG_BLOCK8_SRC_CONFIG_MSB                                           15
+#define GCREG_BLOCK8_SRC_CONFIG_LSB                                            3
+#define GCREG_BLOCK8_SRC_CONFIG_BLK                                            0
+#define GCREG_BLOCK8_SRC_CONFIG_Count                                          8
+#define GCREG_BLOCK8_SRC_CONFIG_FieldMask                             0xDF30B1C0
+#define GCREG_BLOCK8_SRC_CONFIG_ReadMask                              0xDF30B1C0
+#define GCREG_BLOCK8_SRC_CONFIG_WriteMask                             0xDF30B1C0
+#define GCREG_BLOCK8_SRC_CONFIG_ResetValue                            0x00000000
+
+/* Control source endianess. */
+#define GCREG_BLOCK8_SRC_CONFIG_ENDIAN_CONTROL                           31 : 30
+#define GCREG_BLOCK8_SRC_CONFIG_ENDIAN_CONTROL_End                            31
+#define GCREG_BLOCK8_SRC_CONFIG_ENDIAN_CONTROL_Start                          30
+#define GCREG_BLOCK8_SRC_CONFIG_ENDIAN_CONTROL_Type                          U02
+#define   GCREG_BLOCK8_SRC_CONFIG_ENDIAN_CONTROL_NO_SWAP                     0x0
+#define   GCREG_BLOCK8_SRC_CONFIG_ENDIAN_CONTROL_SWAP_WORD                   0x1
+#define   GCREG_BLOCK8_SRC_CONFIG_ENDIAN_CONTROL_SWAP_DWORD                  0x2
+
+/* Defines the pixel format of the source surface. */
+#define GCREG_BLOCK8_SRC_CONFIG_SOURCE_FORMAT                            28 : 24
+#define GCREG_BLOCK8_SRC_CONFIG_SOURCE_FORMAT_End                             28
+#define GCREG_BLOCK8_SRC_CONFIG_SOURCE_FORMAT_Start                           24
+#define GCREG_BLOCK8_SRC_CONFIG_SOURCE_FORMAT_Type                           U05
+#define   GCREG_BLOCK8_SRC_CONFIG_SOURCE_FORMAT_X4R4G4B4                    0x00
+#define   GCREG_BLOCK8_SRC_CONFIG_SOURCE_FORMAT_A4R4G4B4                    0x01
+#define   GCREG_BLOCK8_SRC_CONFIG_SOURCE_FORMAT_X1R5G5B5                    0x02
+#define   GCREG_BLOCK8_SRC_CONFIG_SOURCE_FORMAT_A1R5G5B5                    0x03
+#define   GCREG_BLOCK8_SRC_CONFIG_SOURCE_FORMAT_R5G6B5                      0x04
+#define   GCREG_BLOCK8_SRC_CONFIG_SOURCE_FORMAT_X8R8G8B8                    0x05
+#define   GCREG_BLOCK8_SRC_CONFIG_SOURCE_FORMAT_A8R8G8B8                    0x06
+#define   GCREG_BLOCK8_SRC_CONFIG_SOURCE_FORMAT_YUY2                        0x07
+#define   GCREG_BLOCK8_SRC_CONFIG_SOURCE_FORMAT_UYVY                        0x08
+#define   GCREG_BLOCK8_SRC_CONFIG_SOURCE_FORMAT_INDEX8                      0x09
+#define   GCREG_BLOCK8_SRC_CONFIG_SOURCE_FORMAT_MONOCHROME                  0x0A
+#define   GCREG_BLOCK8_SRC_CONFIG_SOURCE_FORMAT_YV12                        0x0F
+#define   GCREG_BLOCK8_SRC_CONFIG_SOURCE_FORMAT_A8                          0x10
+#define   GCREG_BLOCK8_SRC_CONFIG_SOURCE_FORMAT_NV12                        0x11
+#define   GCREG_BLOCK8_SRC_CONFIG_SOURCE_FORMAT_NV16                        0x12
+#define   GCREG_BLOCK8_SRC_CONFIG_SOURCE_FORMAT_RG16                        0x13
+
+/* Color channel swizzles. */
+#define GCREG_BLOCK8_SRC_CONFIG_SWIZZLE                                  21 : 20
+#define GCREG_BLOCK8_SRC_CONFIG_SWIZZLE_End                                   21
+#define GCREG_BLOCK8_SRC_CONFIG_SWIZZLE_Start                                 20
+#define GCREG_BLOCK8_SRC_CONFIG_SWIZZLE_Type                                 U02
+#define   GCREG_BLOCK8_SRC_CONFIG_SWIZZLE_ARGB                               0x0
+#define   GCREG_BLOCK8_SRC_CONFIG_SWIZZLE_RGBA                               0x1
+#define   GCREG_BLOCK8_SRC_CONFIG_SWIZZLE_ABGR                               0x2
+#define   GCREG_BLOCK8_SRC_CONFIG_SWIZZLE_BGRA                               0x3
+
+/* Mono expansion: if 0, transparency color will be 0, otherwise transparency **
+** color will be 1.                                                           */
+#define GCREG_BLOCK8_SRC_CONFIG_MONO_TRANSPARENCY                        15 : 15
+#define GCREG_BLOCK8_SRC_CONFIG_MONO_TRANSPARENCY_End                         15
+#define GCREG_BLOCK8_SRC_CONFIG_MONO_TRANSPARENCY_Start                       15
+#define GCREG_BLOCK8_SRC_CONFIG_MONO_TRANSPARENCY_Type                       U01
+#define   GCREG_BLOCK8_SRC_CONFIG_MONO_TRANSPARENCY_BACKGROUND               0x0
+#define   GCREG_BLOCK8_SRC_CONFIG_MONO_TRANSPARENCY_FOREGROUND               0x1
+
+/* Mono expansion or masked blit: stream packing in pixels. Determines how    **
+** many horizontal pixels are there per each 32-bit chunk. For example, if    **
+** set to Packed8, each 32-bit chunk is 8-pixel wide, which also means that   **
+** it defines 4 vertical lines of pixels.                                     */
+#define GCREG_BLOCK8_SRC_CONFIG_PACK                                     13 : 12
+#define GCREG_BLOCK8_SRC_CONFIG_PACK_End                                      13
+#define GCREG_BLOCK8_SRC_CONFIG_PACK_Start                                    12
+#define GCREG_BLOCK8_SRC_CONFIG_PACK_Type                                    U02
+#define   GCREG_BLOCK8_SRC_CONFIG_PACK_PACKED8                               0x0
+#define   GCREG_BLOCK8_SRC_CONFIG_PACK_PACKED16                              0x1
+#define   GCREG_BLOCK8_SRC_CONFIG_PACK_PACKED32                              0x2
+#define   GCREG_BLOCK8_SRC_CONFIG_PACK_UNPACKED                              0x3
+
+/* Source data location: set to STREAM for mono expansion blits or masked     **
+** blits. For mono expansion blits the complete bitmap comes from the command **
+** stream. For masked blits the source data comes from the memory and the     **
+** mask from the command stream.                                              */
+#define GCREG_BLOCK8_SRC_CONFIG_LOCATION                                   8 : 8
+#define GCREG_BLOCK8_SRC_CONFIG_LOCATION_End                                   8
+#define GCREG_BLOCK8_SRC_CONFIG_LOCATION_Start                                 8
+#define GCREG_BLOCK8_SRC_CONFIG_LOCATION_Type                                U01
+#define   GCREG_BLOCK8_SRC_CONFIG_LOCATION_MEMORY                            0x0
+#define   GCREG_BLOCK8_SRC_CONFIG_LOCATION_STREAM                            0x1
+
+/* Source linear/tiled address computation control. */
+#define GCREG_BLOCK8_SRC_CONFIG_TILED                                      7 : 7
+#define GCREG_BLOCK8_SRC_CONFIG_TILED_End                                      7
+#define GCREG_BLOCK8_SRC_CONFIG_TILED_Start                                    7
+#define GCREG_BLOCK8_SRC_CONFIG_TILED_Type                                   U01
+#define   GCREG_BLOCK8_SRC_CONFIG_TILED_DISABLED                             0x0
+#define   GCREG_BLOCK8_SRC_CONFIG_TILED_ENABLED                              0x1
+
+/* If set to ABSOLUTE, the source coordinates are treated as absolute         **
+** coordinates inside the source surface. If set to RELATIVE, the source      **
+** coordinates are treated as the offsets from the destination coordinates    **
+** with the source size equal to the size of the destination.                 */
+#define GCREG_BLOCK8_SRC_CONFIG_SRC_RELATIVE                               6 : 6
+#define GCREG_BLOCK8_SRC_CONFIG_SRC_RELATIVE_End                               6
+#define GCREG_BLOCK8_SRC_CONFIG_SRC_RELATIVE_Start                             6
+#define GCREG_BLOCK8_SRC_CONFIG_SRC_RELATIVE_Type                            U01
+#define   GCREG_BLOCK8_SRC_CONFIG_SRC_RELATIVE_ABSOLUTE                      0x0
+#define   GCREG_BLOCK8_SRC_CONFIG_SRC_RELATIVE_RELATIVE                      0x1
+
+/*******************************************************************************
+** State gcregBlock8SrcOrigin
+*/
+
+/* Absolute or relative (see SRC_RELATIVE field of gcregBlock8SrcConfig
+** register) X and Y coordinates in pixels of the top left corner of the
+** source rectangle within the source surface.
+*/
+
+#define gcregBlock8SrcOriginRegAddrs                                      0x4AA0
+#define GCREG_BLOCK8_SRC_ORIGIN_MSB                                           15
+#define GCREG_BLOCK8_SRC_ORIGIN_LSB                                            3
+#define GCREG_BLOCK8_SRC_ORIGIN_BLK                                            0
+#define GCREG_BLOCK8_SRC_ORIGIN_Count                                          8
+#define GCREG_BLOCK8_SRC_ORIGIN_FieldMask                             0xFFFFFFFF
+#define GCREG_BLOCK8_SRC_ORIGIN_ReadMask                              0xFFFFFFFF
+#define GCREG_BLOCK8_SRC_ORIGIN_WriteMask                             0xFFFFFFFF
+#define GCREG_BLOCK8_SRC_ORIGIN_ResetValue                            0x00000000
+
+#define GCREG_BLOCK8_SRC_ORIGIN_Y                                        31 : 16
+#define GCREG_BLOCK8_SRC_ORIGIN_Y_End                                         31
+#define GCREG_BLOCK8_SRC_ORIGIN_Y_Start                                       16
+#define GCREG_BLOCK8_SRC_ORIGIN_Y_Type                                       U16
+
+#define GCREG_BLOCK8_SRC_ORIGIN_X                                         15 : 0
+#define GCREG_BLOCK8_SRC_ORIGIN_X_End                                         15
+#define GCREG_BLOCK8_SRC_ORIGIN_X_Start                                        0
+#define GCREG_BLOCK8_SRC_ORIGIN_X_Type                                       U16
+
+/*******************************************************************************
+** State gcregBlock8SrcSize
+*/
+
+/* Width and height of the source rectangle in pixels. If the source is
+** relative (see SRC_RELATIVE field of gcregBlock8SrcConfig register) or a
+** regular bitblt is being performed without stretching, this register is
+** ignored and the source size is assumed to be the same as the destination.
+*/
+
+#define gcregBlock8SrcSizeRegAddrs                                        0x4AA8
+#define GCREG_BLOCK8_SRC_SIZE_MSB                                             15
+#define GCREG_BLOCK8_SRC_SIZE_LSB                                              3
+#define GCREG_BLOCK8_SRC_SIZE_BLK                                              0
+#define GCREG_BLOCK8_SRC_SIZE_Count                                            8
+#define GCREG_BLOCK8_SRC_SIZE_FieldMask                               0xFFFFFFFF
+#define GCREG_BLOCK8_SRC_SIZE_ReadMask                                0xFFFFFFFF
+#define GCREG_BLOCK8_SRC_SIZE_WriteMask                               0xFFFFFFFF
+#define GCREG_BLOCK8_SRC_SIZE_ResetValue                              0x00000000
+
+#define GCREG_BLOCK8_SRC_SIZE_Y                                          31 : 16
+#define GCREG_BLOCK8_SRC_SIZE_Y_End                                           31
+#define GCREG_BLOCK8_SRC_SIZE_Y_Start                                         16
+#define GCREG_BLOCK8_SRC_SIZE_Y_Type                                         U16
+
+#define GCREG_BLOCK8_SRC_SIZE_X                                           15 : 0
+#define GCREG_BLOCK8_SRC_SIZE_X_End                                           15
+#define GCREG_BLOCK8_SRC_SIZE_X_Start                                          0
+#define GCREG_BLOCK8_SRC_SIZE_X_Type                                         U16
+
+/*******************************************************************************
+** State gcregBlock8SrcColorBg
+*/
+
+/* Select the color where source becomes transparent. It must be programmed
+** in A8R8G8B8 format.
+*/
+
+#define gcregBlock8SrcColorBgRegAddrs                                     0x4AB0
+#define GCREG_BLOCK8_SRC_COLOR_BG_MSB                                         15
+#define GCREG_BLOCK8_SRC_COLOR_BG_LSB                                          3
+#define GCREG_BLOCK8_SRC_COLOR_BG_BLK                                          0
+#define GCREG_BLOCK8_SRC_COLOR_BG_Count                                        8
+#define GCREG_BLOCK8_SRC_COLOR_BG_FieldMask                           0xFFFFFFFF
+#define GCREG_BLOCK8_SRC_COLOR_BG_ReadMask                            0xFFFFFFFF
+#define GCREG_BLOCK8_SRC_COLOR_BG_WriteMask                           0xFFFFFFFF
+#define GCREG_BLOCK8_SRC_COLOR_BG_ResetValue                          0x00000000
+
+#define GCREG_BLOCK8_SRC_COLOR_BG_ALPHA                                  31 : 24
+#define GCREG_BLOCK8_SRC_COLOR_BG_ALPHA_End                                   31
+#define GCREG_BLOCK8_SRC_COLOR_BG_ALPHA_Start                                 24
+#define GCREG_BLOCK8_SRC_COLOR_BG_ALPHA_Type                                 U08
+
+#define GCREG_BLOCK8_SRC_COLOR_BG_RED                                    23 : 16
+#define GCREG_BLOCK8_SRC_COLOR_BG_RED_End                                     23
+#define GCREG_BLOCK8_SRC_COLOR_BG_RED_Start                                   16
+#define GCREG_BLOCK8_SRC_COLOR_BG_RED_Type                                   U08
+
+#define GCREG_BLOCK8_SRC_COLOR_BG_GREEN                                   15 : 8
+#define GCREG_BLOCK8_SRC_COLOR_BG_GREEN_End                                   15
+#define GCREG_BLOCK8_SRC_COLOR_BG_GREEN_Start                                  8
+#define GCREG_BLOCK8_SRC_COLOR_BG_GREEN_Type                                 U08
+
+#define GCREG_BLOCK8_SRC_COLOR_BG_BLUE                                     7 : 0
+#define GCREG_BLOCK8_SRC_COLOR_BG_BLUE_End                                     7
+#define GCREG_BLOCK8_SRC_COLOR_BG_BLUE_Start                                   0
+#define GCREG_BLOCK8_SRC_COLOR_BG_BLUE_Type                                  U08
+
+/*******************************************************************************
+** State gcregBlock8Rop
+*/
+
+/* Raster operation foreground and background codes. Even though ROP is not
+** used in CLEAR, HOR_FILTER_BLT, VER_FILTER_BLT and alpha-eanbled BIT_BLTs,
+** ROP code still has to be programmed, because the engine makes the decision
+** whether source, destination and pattern are involved in the current
+** operation and the correct decision is essential for the engine to complete
+** the operation as expected.
+*/
+
+#define gcregBlock8RopRegAddrs                                            0x4AB8
+#define GCREG_BLOCK8_ROP_MSB                                                  15
+#define GCREG_BLOCK8_ROP_LSB                                                   3
+#define GCREG_BLOCK8_ROP_BLK                                                   0
+#define GCREG_BLOCK8_ROP_Count                                                 8
+#define GCREG_BLOCK8_ROP_FieldMask                                    0x0030FFFF
+#define GCREG_BLOCK8_ROP_ReadMask                                     0x0030FFFF
+#define GCREG_BLOCK8_ROP_WriteMask                                    0x0030FFFF
+#define GCREG_BLOCK8_ROP_ResetValue                                   0x00000000
+
+/* ROP type: ROP2, ROP3 or ROP4 */
+#define GCREG_BLOCK8_ROP_TYPE                                            21 : 20
+#define GCREG_BLOCK8_ROP_TYPE_End                                             21
+#define GCREG_BLOCK8_ROP_TYPE_Start                                           20
+#define GCREG_BLOCK8_ROP_TYPE_Type                                           U02
+#define   GCREG_BLOCK8_ROP_TYPE_ROP2_PATTERN                                 0x0
+#define   GCREG_BLOCK8_ROP_TYPE_ROP2_SOURCE                                  0x1
+#define   GCREG_BLOCK8_ROP_TYPE_ROP3                                         0x2
+#define   GCREG_BLOCK8_ROP_TYPE_ROP4                                         0x3
+
+/* Background ROP code is used for transparent pixels. */
+#define GCREG_BLOCK8_ROP_ROP_BG                                           15 : 8
+#define GCREG_BLOCK8_ROP_ROP_BG_End                                           15
+#define GCREG_BLOCK8_ROP_ROP_BG_Start                                          8
+#define GCREG_BLOCK8_ROP_ROP_BG_Type                                         U08
+
+/* Background ROP code is used for opaque pixels. */
+#define GCREG_BLOCK8_ROP_ROP_FG                                            7 : 0
+#define GCREG_BLOCK8_ROP_ROP_FG_End                                            7
+#define GCREG_BLOCK8_ROP_ROP_FG_Start                                          0
+#define GCREG_BLOCK8_ROP_ROP_FG_Type                                         U08
+
+/*******************************************************************************
+** State gcregBlock8AlphaControl
+*/
+
+#define gcregBlock8AlphaControlRegAddrs                                   0x4AC0
+#define GCREG_BLOCK8_ALPHA_CONTROL_MSB                                        15
+#define GCREG_BLOCK8_ALPHA_CONTROL_LSB                                         3
+#define GCREG_BLOCK8_ALPHA_CONTROL_BLK                                         0
+#define GCREG_BLOCK8_ALPHA_CONTROL_Count                                       8
+#define GCREG_BLOCK8_ALPHA_CONTROL_FieldMask                          0x00000001
+#define GCREG_BLOCK8_ALPHA_CONTROL_ReadMask                           0x00000001
+#define GCREG_BLOCK8_ALPHA_CONTROL_WriteMask                          0x00000001
+#define GCREG_BLOCK8_ALPHA_CONTROL_ResetValue                         0x00000000
+
+#define GCREG_BLOCK8_ALPHA_CONTROL_ENABLE                                  0 : 0
+#define GCREG_BLOCK8_ALPHA_CONTROL_ENABLE_End                                  0
+#define GCREG_BLOCK8_ALPHA_CONTROL_ENABLE_Start                                0
+#define GCREG_BLOCK8_ALPHA_CONTROL_ENABLE_Type                               U01
+#define   GCREG_BLOCK8_ALPHA_CONTROL_ENABLE_OFF                              0x0
+#define   GCREG_BLOCK8_ALPHA_CONTROL_ENABLE_ON                               0x1
+
+/*******************************************************************************
+** State gcregBlock8AlphaModes
+*/
+
+#define gcregBlock8AlphaModesRegAddrs                                     0x4AC8
+#define GCREG_BLOCK8_ALPHA_MODES_MSB                                          15
+#define GCREG_BLOCK8_ALPHA_MODES_LSB                                           3
+#define GCREG_BLOCK8_ALPHA_MODES_BLK                                           0
+#define GCREG_BLOCK8_ALPHA_MODES_Count                                         8
+#define GCREG_BLOCK8_ALPHA_MODES_FieldMask                            0xFF003311
+#define GCREG_BLOCK8_ALPHA_MODES_ReadMask                             0xFF003311
+#define GCREG_BLOCK8_ALPHA_MODES_WriteMask                            0xFF003311
+#define GCREG_BLOCK8_ALPHA_MODES_ResetValue                           0x00000000
+
+#define GCREG_BLOCK8_ALPHA_MODES_SRC_ALPHA_MODE                            0 : 0
+#define GCREG_BLOCK8_ALPHA_MODES_SRC_ALPHA_MODE_End                            0
+#define GCREG_BLOCK8_ALPHA_MODES_SRC_ALPHA_MODE_Start                          0
+#define GCREG_BLOCK8_ALPHA_MODES_SRC_ALPHA_MODE_Type                         U01
+#define   GCREG_BLOCK8_ALPHA_MODES_SRC_ALPHA_MODE_NORMAL                     0x0
+#define   GCREG_BLOCK8_ALPHA_MODES_SRC_ALPHA_MODE_INVERSED                   0x1
+
+#define GCREG_BLOCK8_ALPHA_MODES_DST_ALPHA_MODE                            4 : 4
+#define GCREG_BLOCK8_ALPHA_MODES_DST_ALPHA_MODE_End                            4
+#define GCREG_BLOCK8_ALPHA_MODES_DST_ALPHA_MODE_Start                          4
+#define GCREG_BLOCK8_ALPHA_MODES_DST_ALPHA_MODE_Type                         U01
+#define   GCREG_BLOCK8_ALPHA_MODES_DST_ALPHA_MODE_NORMAL                     0x0
+#define   GCREG_BLOCK8_ALPHA_MODES_DST_ALPHA_MODE_INVERSED                   0x1
+
+#define GCREG_BLOCK8_ALPHA_MODES_GLOBAL_SRC_ALPHA_MODE                     9 : 8
+#define GCREG_BLOCK8_ALPHA_MODES_GLOBAL_SRC_ALPHA_MODE_End                     9
+#define GCREG_BLOCK8_ALPHA_MODES_GLOBAL_SRC_ALPHA_MODE_Start                   8
+#define GCREG_BLOCK8_ALPHA_MODES_GLOBAL_SRC_ALPHA_MODE_Type                  U02
+#define   GCREG_BLOCK8_ALPHA_MODES_GLOBAL_SRC_ALPHA_MODE_NORMAL              0x0
+#define   GCREG_BLOCK8_ALPHA_MODES_GLOBAL_SRC_ALPHA_MODE_GLOBAL              0x1
+#define   GCREG_BLOCK8_ALPHA_MODES_GLOBAL_SRC_ALPHA_MODE_SCALED              0x2
+
+#define GCREG_BLOCK8_ALPHA_MODES_GLOBAL_DST_ALPHA_MODE                   13 : 12
+#define GCREG_BLOCK8_ALPHA_MODES_GLOBAL_DST_ALPHA_MODE_End                    13
+#define GCREG_BLOCK8_ALPHA_MODES_GLOBAL_DST_ALPHA_MODE_Start                  12
+#define GCREG_BLOCK8_ALPHA_MODES_GLOBAL_DST_ALPHA_MODE_Type                  U02
+#define   GCREG_BLOCK8_ALPHA_MODES_GLOBAL_DST_ALPHA_MODE_NORMAL              0x0
+#define   GCREG_BLOCK8_ALPHA_MODES_GLOBAL_DST_ALPHA_MODE_GLOBAL              0x1
+#define   GCREG_BLOCK8_ALPHA_MODES_GLOBAL_DST_ALPHA_MODE_SCALED              0x2
+
+#define GCREG_BLOCK8_ALPHA_MODES_SRC_BLENDING_MODE                       26 : 24
+#define GCREG_BLOCK8_ALPHA_MODES_SRC_BLENDING_MODE_End                        26
+#define GCREG_BLOCK8_ALPHA_MODES_SRC_BLENDING_MODE_Start                      24
+#define GCREG_BLOCK8_ALPHA_MODES_SRC_BLENDING_MODE_Type                      U03
+#define   GCREG_BLOCK8_ALPHA_MODES_SRC_BLENDING_MODE_ZERO                    0x0
+#define   GCREG_BLOCK8_ALPHA_MODES_SRC_BLENDING_MODE_ONE                     0x1
+#define   GCREG_BLOCK8_ALPHA_MODES_SRC_BLENDING_MODE_NORMAL                  0x2
+#define   GCREG_BLOCK8_ALPHA_MODES_SRC_BLENDING_MODE_INVERSED                0x3
+#define   GCREG_BLOCK8_ALPHA_MODES_SRC_BLENDING_MODE_COLOR                   0x4
+#define   GCREG_BLOCK8_ALPHA_MODES_SRC_BLENDING_MODE_COLOR_INVERSED          0x5
+#define   GCREG_BLOCK8_ALPHA_MODES_SRC_BLENDING_MODE_SATURATED_ALPHA         0x6
+#define   GCREG_BLOCK8_ALPHA_MODES_SRC_BLENDING_MODE_SATURATED_DEST_ALPHA    0x7
+
+/* Src Blending factor is calculate from Src alpha. */
+#define GCREG_BLOCK8_ALPHA_MODES_SRC_ALPHA_FACTOR                        27 : 27
+#define GCREG_BLOCK8_ALPHA_MODES_SRC_ALPHA_FACTOR_End                         27
+#define GCREG_BLOCK8_ALPHA_MODES_SRC_ALPHA_FACTOR_Start                       27
+#define GCREG_BLOCK8_ALPHA_MODES_SRC_ALPHA_FACTOR_Type                       U01
+#define   GCREG_BLOCK8_ALPHA_MODES_SRC_ALPHA_FACTOR_DISABLED                 0x0
+#define   GCREG_BLOCK8_ALPHA_MODES_SRC_ALPHA_FACTOR_ENABLED                  0x1
+
+#define GCREG_BLOCK8_ALPHA_MODES_DST_BLENDING_MODE                       30 : 28
+#define GCREG_BLOCK8_ALPHA_MODES_DST_BLENDING_MODE_End                        30
+#define GCREG_BLOCK8_ALPHA_MODES_DST_BLENDING_MODE_Start                      28
+#define GCREG_BLOCK8_ALPHA_MODES_DST_BLENDING_MODE_Type                      U03
+#define   GCREG_BLOCK8_ALPHA_MODES_DST_BLENDING_MODE_ZERO                    0x0
+#define   GCREG_BLOCK8_ALPHA_MODES_DST_BLENDING_MODE_ONE                     0x1
+#define   GCREG_BLOCK8_ALPHA_MODES_DST_BLENDING_MODE_NORMAL                  0x2
+#define   GCREG_BLOCK8_ALPHA_MODES_DST_BLENDING_MODE_INVERSED                0x3
+#define   GCREG_BLOCK8_ALPHA_MODES_DST_BLENDING_MODE_COLOR                   0x4
+#define   GCREG_BLOCK8_ALPHA_MODES_DST_BLENDING_MODE_COLOR_INVERSED          0x5
+#define   GCREG_BLOCK8_ALPHA_MODES_DST_BLENDING_MODE_SATURATED_ALPHA         0x6
+#define   GCREG_BLOCK8_ALPHA_MODES_DST_BLENDING_MODE_SATURATED_DEST_ALPHA    0x7
+
+/* Dst Blending factor is calculate from Dst alpha. */
+#define GCREG_BLOCK8_ALPHA_MODES_DST_ALPHA_FACTOR                        31 : 31
+#define GCREG_BLOCK8_ALPHA_MODES_DST_ALPHA_FACTOR_End                         31
+#define GCREG_BLOCK8_ALPHA_MODES_DST_ALPHA_FACTOR_Start                       31
+#define GCREG_BLOCK8_ALPHA_MODES_DST_ALPHA_FACTOR_Type                       U01
+#define   GCREG_BLOCK8_ALPHA_MODES_DST_ALPHA_FACTOR_DISABLED                 0x0
+#define   GCREG_BLOCK8_ALPHA_MODES_DST_ALPHA_FACTOR_ENABLED                  0x1
+
+/*******************************************************************************
+** State gcregBlock8AddressU
+*/
+
+/* 32-bit aligned base address of the source U plane. */
+
+#define gcregBlock8UPlaneAddressRegAddrs                                  0x4AD0
+#define GCREG_BLOCK8_UPLANE_ADDRESS_MSB                                       15
+#define GCREG_BLOCK8_UPLANE_ADDRESS_LSB                                        3
+#define GCREG_BLOCK8_UPLANE_ADDRESS_BLK                                        0
+#define GCREG_BLOCK8_UPLANE_ADDRESS_Count                                      8
+#define GCREG_BLOCK8_UPLANE_ADDRESS_FieldMask                         0xFFFFFFFF
+#define GCREG_BLOCK8_UPLANE_ADDRESS_ReadMask                          0xFFFFFFFC
+#define GCREG_BLOCK8_UPLANE_ADDRESS_WriteMask                         0xFFFFFFFC
+#define GCREG_BLOCK8_UPLANE_ADDRESS_ResetValue                        0x00000000
+
+#define GCREG_BLOCK8_UPLANE_ADDRESS_ADDRESS                               31 : 0
+#define GCREG_BLOCK8_UPLANE_ADDRESS_ADDRESS_End                               30
+#define GCREG_BLOCK8_UPLANE_ADDRESS_ADDRESS_Start                              0
+#define GCREG_BLOCK8_UPLANE_ADDRESS_ADDRESS_Type                             U31
+
+/*******************************************************************************
+** State gcregBlock8StrideU
+*/
+
+/* Stride of the source U plane in bytes. */
+
+#define gcregBlock8UPlaneStrideRegAddrs                                   0x4AD8
+#define GCREG_BLOCK8_UPLANE_STRIDE_MSB                                        15
+#define GCREG_BLOCK8_UPLANE_STRIDE_LSB                                         3
+#define GCREG_BLOCK8_UPLANE_STRIDE_BLK                                         0
+#define GCREG_BLOCK8_UPLANE_STRIDE_Count                                       8
+#define GCREG_BLOCK8_UPLANE_STRIDE_FieldMask                          0x0003FFFF
+#define GCREG_BLOCK8_UPLANE_STRIDE_ReadMask                           0x0003FFFC
+#define GCREG_BLOCK8_UPLANE_STRIDE_WriteMask                          0x0003FFFC
+#define GCREG_BLOCK8_UPLANE_STRIDE_ResetValue                         0x00000000
+
+#define GCREG_BLOCK8_UPLANE_STRIDE_STRIDE                                 17 : 0
+#define GCREG_BLOCK8_UPLANE_STRIDE_STRIDE_End                                 17
+#define GCREG_BLOCK8_UPLANE_STRIDE_STRIDE_Start                                0
+#define GCREG_BLOCK8_UPLANE_STRIDE_STRIDE_Type                               U18
+
+/*******************************************************************************
+** State gcregBlock8AddressV
+*/
+
+/* 32-bit aligned base address of the source V plane. */
+
+#define gcregBlock8VPlaneAddressRegAddrs                                  0x4AE0
+#define GCREG_BLOCK8_VPLANE_ADDRESS_MSB                                       15
+#define GCREG_BLOCK8_VPLANE_ADDRESS_LSB                                        3
+#define GCREG_BLOCK8_VPLANE_ADDRESS_BLK                                        0
+#define GCREG_BLOCK8_VPLANE_ADDRESS_Count                                      8
+#define GCREG_BLOCK8_VPLANE_ADDRESS_FieldMask                         0xFFFFFFFF
+#define GCREG_BLOCK8_VPLANE_ADDRESS_ReadMask                          0xFFFFFFFC
+#define GCREG_BLOCK8_VPLANE_ADDRESS_WriteMask                         0xFFFFFFFC
+#define GCREG_BLOCK8_VPLANE_ADDRESS_ResetValue                        0x00000000
+
+#define GCREG_BLOCK8_VPLANE_ADDRESS_ADDRESS                               31 : 0
+#define GCREG_BLOCK8_VPLANE_ADDRESS_ADDRESS_End                               30
+#define GCREG_BLOCK8_VPLANE_ADDRESS_ADDRESS_Start                              0
+#define GCREG_BLOCK8_VPLANE_ADDRESS_ADDRESS_Type                             U31
+
+/*******************************************************************************
+** State gcregBlock8StrideV
+*/
+
+/* Stride of the source V plane in bytes. */
+
+#define gcregBlock8VPlaneStrideRegAddrs                                   0x4AE8
+#define GCREG_BLOCK8_VPLANE_STRIDE_MSB                                        15
+#define GCREG_BLOCK8_VPLANE_STRIDE_LSB                                         3
+#define GCREG_BLOCK8_VPLANE_STRIDE_BLK                                         0
+#define GCREG_BLOCK8_VPLANE_STRIDE_Count                                       8
+#define GCREG_BLOCK8_VPLANE_STRIDE_FieldMask                          0x0003FFFF
+#define GCREG_BLOCK8_VPLANE_STRIDE_ReadMask                           0x0003FFFC
+#define GCREG_BLOCK8_VPLANE_STRIDE_WriteMask                          0x0003FFFC
+#define GCREG_BLOCK8_VPLANE_STRIDE_ResetValue                         0x00000000
+
+#define GCREG_BLOCK8_VPLANE_STRIDE_STRIDE                                 17 : 0
+#define GCREG_BLOCK8_VPLANE_STRIDE_STRIDE_End                                 17
+#define GCREG_BLOCK8_VPLANE_STRIDE_STRIDE_Start                                0
+#define GCREG_BLOCK8_VPLANE_STRIDE_STRIDE_Type                               U18
+
+/*******************************************************************************
+** State gcregBlock8SrcRotationHeight
+*/
+
+/* 180/270 degree rotation configuration for the Source surface. Height field
+** specifies the height of the surface in pixels.
+*/
+
+#define gcregBlock8SrcRotationHeightRegAddrs                              0x4AF0
+#define GCREG_BLOCK8_SRC_ROTATION_HEIGHT_MSB                                  15
+#define GCREG_BLOCK8_SRC_ROTATION_HEIGHT_LSB                                   3
+#define GCREG_BLOCK8_SRC_ROTATION_HEIGHT_BLK                                   0
+#define GCREG_BLOCK8_SRC_ROTATION_HEIGHT_Count                                 8
+#define GCREG_BLOCK8_SRC_ROTATION_HEIGHT_FieldMask                    0x0000FFFF
+#define GCREG_BLOCK8_SRC_ROTATION_HEIGHT_ReadMask                     0x0000FFFF
+#define GCREG_BLOCK8_SRC_ROTATION_HEIGHT_WriteMask                    0x0000FFFF
+#define GCREG_BLOCK8_SRC_ROTATION_HEIGHT_ResetValue                   0x00000000
+
+#define GCREG_BLOCK8_SRC_ROTATION_HEIGHT_HEIGHT                           15 : 0
+#define GCREG_BLOCK8_SRC_ROTATION_HEIGHT_HEIGHT_End                           15
+#define GCREG_BLOCK8_SRC_ROTATION_HEIGHT_HEIGHT_Start                          0
+#define GCREG_BLOCK8_SRC_ROTATION_HEIGHT_HEIGHT_Type                         U16
+
+/*******************************************************************************
+** State gcregBlock8RotAngle
+*/
+
+/* 0/90/180/270 degree rotation configuration for the Source surface. Height
+** field specifies the height of the surface in pixels.
+*/
+
+#define gcregBlock8RotAngleRegAddrs                                       0x4AF8
+#define GCREG_BLOCK8_ROT_ANGLE_MSB                                            15
+#define GCREG_BLOCK8_ROT_ANGLE_LSB                                             3
+#define GCREG_BLOCK8_ROT_ANGLE_BLK                                             0
+#define GCREG_BLOCK8_ROT_ANGLE_Count                                           8
+#define GCREG_BLOCK8_ROT_ANGLE_FieldMask                              0x000BB33F
+#define GCREG_BLOCK8_ROT_ANGLE_ReadMask                               0x000BB33F
+#define GCREG_BLOCK8_ROT_ANGLE_WriteMask                              0x000BB33F
+#define GCREG_BLOCK8_ROT_ANGLE_ResetValue                             0x00000000
+
+#define GCREG_BLOCK8_ROT_ANGLE_SRC                                         2 : 0
+#define GCREG_BLOCK8_ROT_ANGLE_SRC_End                                         2
+#define GCREG_BLOCK8_ROT_ANGLE_SRC_Start                                       0
+#define GCREG_BLOCK8_ROT_ANGLE_SRC_Type                                      U03
+#define   GCREG_BLOCK8_ROT_ANGLE_SRC_ROT0                                    0x0
+#define   GCREG_BLOCK8_ROT_ANGLE_SRC_FLIP_X                                  0x1
+#define   GCREG_BLOCK8_ROT_ANGLE_SRC_FLIP_Y                                  0x2
+#define   GCREG_BLOCK8_ROT_ANGLE_SRC_ROT90                                   0x4
+#define   GCREG_BLOCK8_ROT_ANGLE_SRC_ROT180                                  0x5
+#define   GCREG_BLOCK8_ROT_ANGLE_SRC_ROT270                                  0x6
+
+#define GCREG_BLOCK8_ROT_ANGLE_DST                                         5 : 3
+#define GCREG_BLOCK8_ROT_ANGLE_DST_End                                         5
+#define GCREG_BLOCK8_ROT_ANGLE_DST_Start                                       3
+#define GCREG_BLOCK8_ROT_ANGLE_DST_Type                                      U03
+#define   GCREG_BLOCK8_ROT_ANGLE_DST_ROT0                                    0x0
+#define   GCREG_BLOCK8_ROT_ANGLE_DST_FLIP_X                                  0x1
+#define   GCREG_BLOCK8_ROT_ANGLE_DST_FLIP_Y                                  0x2
+#define   GCREG_BLOCK8_ROT_ANGLE_DST_ROT90                                   0x4
+#define   GCREG_BLOCK8_ROT_ANGLE_DST_ROT180                                  0x5
+#define   GCREG_BLOCK8_ROT_ANGLE_DST_ROT270                                  0x6
+
+#define GCREG_BLOCK8_ROT_ANGLE_MASK_SRC                                    8 : 8
+#define GCREG_BLOCK8_ROT_ANGLE_MASK_SRC_End                                    8
+#define GCREG_BLOCK8_ROT_ANGLE_MASK_SRC_Start                                  8
+#define GCREG_BLOCK8_ROT_ANGLE_MASK_SRC_Type                                 U01
+#define   GCREG_BLOCK8_ROT_ANGLE_MASK_SRC_ENABLED                            0x0
+#define   GCREG_BLOCK8_ROT_ANGLE_MASK_SRC_MASKED                             0x1
+
+#define GCREG_BLOCK8_ROT_ANGLE_MASK_DST                                    9 : 9
+#define GCREG_BLOCK8_ROT_ANGLE_MASK_DST_End                                    9
+#define GCREG_BLOCK8_ROT_ANGLE_MASK_DST_Start                                  9
+#define GCREG_BLOCK8_ROT_ANGLE_MASK_DST_Type                                 U01
+#define   GCREG_BLOCK8_ROT_ANGLE_MASK_DST_ENABLED                            0x0
+#define   GCREG_BLOCK8_ROT_ANGLE_MASK_DST_MASKED                             0x1
+
+#define GCREG_BLOCK8_ROT_ANGLE_SRC_MIRROR                                13 : 12
+#define GCREG_BLOCK8_ROT_ANGLE_SRC_MIRROR_End                                 13
+#define GCREG_BLOCK8_ROT_ANGLE_SRC_MIRROR_Start                               12
+#define GCREG_BLOCK8_ROT_ANGLE_SRC_MIRROR_Type                               U02
+#define   GCREG_BLOCK8_ROT_ANGLE_SRC_MIRROR_NONE                             0x0
+#define   GCREG_BLOCK8_ROT_ANGLE_SRC_MIRROR_MIRROR_X                         0x1
+#define   GCREG_BLOCK8_ROT_ANGLE_SRC_MIRROR_MIRROR_Y                         0x2
+#define   GCREG_BLOCK8_ROT_ANGLE_SRC_MIRROR_MIRROR_XY                        0x3
+
+#define GCREG_BLOCK8_ROT_ANGLE_MASK_SRC_MIRROR                           15 : 15
+#define GCREG_BLOCK8_ROT_ANGLE_MASK_SRC_MIRROR_End                            15
+#define GCREG_BLOCK8_ROT_ANGLE_MASK_SRC_MIRROR_Start                          15
+#define GCREG_BLOCK8_ROT_ANGLE_MASK_SRC_MIRROR_Type                          U01
+#define   GCREG_BLOCK8_ROT_ANGLE_MASK_SRC_MIRROR_ENABLED                     0x0
+#define   GCREG_BLOCK8_ROT_ANGLE_MASK_SRC_MIRROR_MASKED                      0x1
+
+#define GCREG_BLOCK8_ROT_ANGLE_DST_MIRROR                                17 : 16
+#define GCREG_BLOCK8_ROT_ANGLE_DST_MIRROR_End                                 17
+#define GCREG_BLOCK8_ROT_ANGLE_DST_MIRROR_Start                               16
+#define GCREG_BLOCK8_ROT_ANGLE_DST_MIRROR_Type                               U02
+#define   GCREG_BLOCK8_ROT_ANGLE_DST_MIRROR_NONE                             0x0
+#define   GCREG_BLOCK8_ROT_ANGLE_DST_MIRROR_MIRROR_X                         0x1
+#define   GCREG_BLOCK8_ROT_ANGLE_DST_MIRROR_MIRROR_Y                         0x2
+#define   GCREG_BLOCK8_ROT_ANGLE_DST_MIRROR_MIRROR_XY                        0x3
+
+#define GCREG_BLOCK8_ROT_ANGLE_MASK_DST_MIRROR                           19 : 19
+#define GCREG_BLOCK8_ROT_ANGLE_MASK_DST_MIRROR_End                            19
+#define GCREG_BLOCK8_ROT_ANGLE_MASK_DST_MIRROR_Start                          19
+#define GCREG_BLOCK8_ROT_ANGLE_MASK_DST_MIRROR_Type                          U01
+#define   GCREG_BLOCK8_ROT_ANGLE_MASK_DST_MIRROR_ENABLED                     0x0
+#define   GCREG_BLOCK8_ROT_ANGLE_MASK_DST_MIRROR_MASKED                      0x1
+
+/*******************************************************************************
+** State gcregBlock8GlobalSrcColor
+*/
+
+/* Defines the global source color and alpha values. */
+
+#define gcregBlock8GlobalSrcColorRegAddrs                                 0x4B00
+#define GCREG_BLOCK8_GLOBAL_SRC_COLOR_MSB                                     15
+#define GCREG_BLOCK8_GLOBAL_SRC_COLOR_LSB                                      3
+#define GCREG_BLOCK8_GLOBAL_SRC_COLOR_BLK                                      0
+#define GCREG_BLOCK8_GLOBAL_SRC_COLOR_Count                                    8
+#define GCREG_BLOCK8_GLOBAL_SRC_COLOR_FieldMask                       0xFFFFFFFF
+#define GCREG_BLOCK8_GLOBAL_SRC_COLOR_ReadMask                        0xFFFFFFFF
+#define GCREG_BLOCK8_GLOBAL_SRC_COLOR_WriteMask                       0xFFFFFFFF
+#define GCREG_BLOCK8_GLOBAL_SRC_COLOR_ResetValue                      0x00000000
+
+#define GCREG_BLOCK8_GLOBAL_SRC_COLOR_ALPHA                              31 : 24
+#define GCREG_BLOCK8_GLOBAL_SRC_COLOR_ALPHA_End                               31
+#define GCREG_BLOCK8_GLOBAL_SRC_COLOR_ALPHA_Start                             24
+#define GCREG_BLOCK8_GLOBAL_SRC_COLOR_ALPHA_Type                             U08
+
+#define GCREG_BLOCK8_GLOBAL_SRC_COLOR_RED                                23 : 16
+#define GCREG_BLOCK8_GLOBAL_SRC_COLOR_RED_End                                 23
+#define GCREG_BLOCK8_GLOBAL_SRC_COLOR_RED_Start                               16
+#define GCREG_BLOCK8_GLOBAL_SRC_COLOR_RED_Type                               U08
+
+#define GCREG_BLOCK8_GLOBAL_SRC_COLOR_GREEN                               15 : 8
+#define GCREG_BLOCK8_GLOBAL_SRC_COLOR_GREEN_End                               15
+#define GCREG_BLOCK8_GLOBAL_SRC_COLOR_GREEN_Start                              8
+#define GCREG_BLOCK8_GLOBAL_SRC_COLOR_GREEN_Type                             U08
+
+#define GCREG_BLOCK8_GLOBAL_SRC_COLOR_BLUE                                 7 : 0
+#define GCREG_BLOCK8_GLOBAL_SRC_COLOR_BLUE_End                                 7
+#define GCREG_BLOCK8_GLOBAL_SRC_COLOR_BLUE_Start                               0
+#define GCREG_BLOCK8_GLOBAL_SRC_COLOR_BLUE_Type                              U08
+
+/*******************************************************************************
+** State gcregBlock8GlobalDestColor
+*/
+
+/* Defines the global destination color and alpha values. */
+
+#define gcregBlock8GlobalDestColorRegAddrs                                0x4B08
+#define GCREG_BLOCK8_GLOBAL_DEST_COLOR_MSB                                    15
+#define GCREG_BLOCK8_GLOBAL_DEST_COLOR_LSB                                     3
+#define GCREG_BLOCK8_GLOBAL_DEST_COLOR_BLK                                     0
+#define GCREG_BLOCK8_GLOBAL_DEST_COLOR_Count                                   8
+#define GCREG_BLOCK8_GLOBAL_DEST_COLOR_FieldMask                      0xFFFFFFFF
+#define GCREG_BLOCK8_GLOBAL_DEST_COLOR_ReadMask                       0xFFFFFFFF
+#define GCREG_BLOCK8_GLOBAL_DEST_COLOR_WriteMask                      0xFFFFFFFF
+#define GCREG_BLOCK8_GLOBAL_DEST_COLOR_ResetValue                     0x00000000
+
+#define GCREG_BLOCK8_GLOBAL_DEST_COLOR_ALPHA                             31 : 24
+#define GCREG_BLOCK8_GLOBAL_DEST_COLOR_ALPHA_End                              31
+#define GCREG_BLOCK8_GLOBAL_DEST_COLOR_ALPHA_Start                            24
+#define GCREG_BLOCK8_GLOBAL_DEST_COLOR_ALPHA_Type                            U08
+
+#define GCREG_BLOCK8_GLOBAL_DEST_COLOR_RED                               23 : 16
+#define GCREG_BLOCK8_GLOBAL_DEST_COLOR_RED_End                                23
+#define GCREG_BLOCK8_GLOBAL_DEST_COLOR_RED_Start                              16
+#define GCREG_BLOCK8_GLOBAL_DEST_COLOR_RED_Type                              U08
+
+#define GCREG_BLOCK8_GLOBAL_DEST_COLOR_GREEN                              15 : 8
+#define GCREG_BLOCK8_GLOBAL_DEST_COLOR_GREEN_End                              15
+#define GCREG_BLOCK8_GLOBAL_DEST_COLOR_GREEN_Start                             8
+#define GCREG_BLOCK8_GLOBAL_DEST_COLOR_GREEN_Type                            U08
+
+#define GCREG_BLOCK8_GLOBAL_DEST_COLOR_BLUE                                7 : 0
+#define GCREG_BLOCK8_GLOBAL_DEST_COLOR_BLUE_End                                7
+#define GCREG_BLOCK8_GLOBAL_DEST_COLOR_BLUE_Start                              0
+#define GCREG_BLOCK8_GLOBAL_DEST_COLOR_BLUE_Type                             U08
+
+/*******************************************************************************
+** State gcregBlock8ColorMultiplyModes
+*/
+
+/* Color modes to multiply Source or Destination pixel color by alpha
+** channel. Alpha can be from global color source or current pixel.
+*/
+
+#define gcregBlock8ColorMultiplyModesRegAddrs                             0x4B10
+#define GCREG_BLOCK8_COLOR_MULTIPLY_MODES_MSB                                 15
+#define GCREG_BLOCK8_COLOR_MULTIPLY_MODES_LSB                                  3
+#define GCREG_BLOCK8_COLOR_MULTIPLY_MODES_BLK                                  0
+#define GCREG_BLOCK8_COLOR_MULTIPLY_MODES_Count                                8
+#define GCREG_BLOCK8_COLOR_MULTIPLY_MODES_FieldMask                   0x00100311
+#define GCREG_BLOCK8_COLOR_MULTIPLY_MODES_ReadMask                    0x00100311
+#define GCREG_BLOCK8_COLOR_MULTIPLY_MODES_WriteMask                   0x00100311
+#define GCREG_BLOCK8_COLOR_MULTIPLY_MODES_ResetValue                  0x00000000
+
+#define GCREG_BLOCK8_COLOR_MULTIPLY_MODES_SRC_PREMULTIPLY                  0 : 0
+#define GCREG_BLOCK8_COLOR_MULTIPLY_MODES_SRC_PREMULTIPLY_End                  0
+#define GCREG_BLOCK8_COLOR_MULTIPLY_MODES_SRC_PREMULTIPLY_Start                0
+#define GCREG_BLOCK8_COLOR_MULTIPLY_MODES_SRC_PREMULTIPLY_Type               U01
+#define   GCREG_BLOCK8_COLOR_MULTIPLY_MODES_SRC_PREMULTIPLY_DISABLE          0x0
+#define   GCREG_BLOCK8_COLOR_MULTIPLY_MODES_SRC_PREMULTIPLY_ENABLE           0x1
+
+#define GCREG_BLOCK8_COLOR_MULTIPLY_MODES_DST_PREMULTIPLY                  4 : 4
+#define GCREG_BLOCK8_COLOR_MULTIPLY_MODES_DST_PREMULTIPLY_End                  4
+#define GCREG_BLOCK8_COLOR_MULTIPLY_MODES_DST_PREMULTIPLY_Start                4
+#define GCREG_BLOCK8_COLOR_MULTIPLY_MODES_DST_PREMULTIPLY_Type               U01
+#define   GCREG_BLOCK8_COLOR_MULTIPLY_MODES_DST_PREMULTIPLY_DISABLE          0x0
+#define   GCREG_BLOCK8_COLOR_MULTIPLY_MODES_DST_PREMULTIPLY_ENABLE           0x1
+
+#define GCREG_BLOCK8_COLOR_MULTIPLY_MODES_SRC_GLOBAL_PREMULTIPLY           9 : 8
+#define GCREG_BLOCK8_COLOR_MULTIPLY_MODES_SRC_GLOBAL_PREMULTIPLY_End           9
+#define GCREG_BLOCK8_COLOR_MULTIPLY_MODES_SRC_GLOBAL_PREMULTIPLY_Start         8
+#define GCREG_BLOCK8_COLOR_MULTIPLY_MODES_SRC_GLOBAL_PREMULTIPLY_Type        U02
+#define   GCREG_BLOCK8_COLOR_MULTIPLY_MODES_SRC_GLOBAL_PREMULTIPLY_DISABLE   0x0
+#define   GCREG_BLOCK8_COLOR_MULTIPLY_MODES_SRC_GLOBAL_PREMULTIPLY_ALPHA     0x1
+#define   GCREG_BLOCK8_COLOR_MULTIPLY_MODES_SRC_GLOBAL_PREMULTIPLY_COLOR     0x2
+
+#define GCREG_BLOCK8_COLOR_MULTIPLY_MODES_DST_DEMULTIPLY                 20 : 20
+#define GCREG_BLOCK8_COLOR_MULTIPLY_MODES_DST_DEMULTIPLY_End                  20
+#define GCREG_BLOCK8_COLOR_MULTIPLY_MODES_DST_DEMULTIPLY_Start                20
+#define GCREG_BLOCK8_COLOR_MULTIPLY_MODES_DST_DEMULTIPLY_Type                U01
+#define   GCREG_BLOCK8_COLOR_MULTIPLY_MODES_DST_DEMULTIPLY_DISABLE           0x0
+#define   GCREG_BLOCK8_COLOR_MULTIPLY_MODES_DST_DEMULTIPLY_ENABLE            0x1
+
+/*******************************************************************************
+** State gcregBlock8Transparency
+*/
+
+#define gcregBlock8TransparencyRegAddrs                                   0x4B18
+#define GCREG_BLOCK8_TRANSPARENCY_MSB                                         15
+#define GCREG_BLOCK8_TRANSPARENCY_LSB                                          3
+#define GCREG_BLOCK8_TRANSPARENCY_BLK                                          0
+#define GCREG_BLOCK8_TRANSPARENCY_Count                                        8
+#define GCREG_BLOCK8_TRANSPARENCY_FieldMask                           0xB3331333
+#define GCREG_BLOCK8_TRANSPARENCY_ReadMask                            0xB3331333
+#define GCREG_BLOCK8_TRANSPARENCY_WriteMask                           0xB3331333
+#define GCREG_BLOCK8_TRANSPARENCY_ResetValue                          0x00000000
+
+/* Source transparency mode. */
+#define GCREG_BLOCK8_TRANSPARENCY_SOURCE                                   1 : 0
+#define GCREG_BLOCK8_TRANSPARENCY_SOURCE_End                                   1
+#define GCREG_BLOCK8_TRANSPARENCY_SOURCE_Start                                 0
+#define GCREG_BLOCK8_TRANSPARENCY_SOURCE_Type                                U02
+#define   GCREG_BLOCK8_TRANSPARENCY_SOURCE_OPAQUE                            0x0
+#define   GCREG_BLOCK8_TRANSPARENCY_SOURCE_MASK                              0x1
+#define   GCREG_BLOCK8_TRANSPARENCY_SOURCE_KEY                               0x2
+
+/* Pattern transparency mode. KEY transparency mode is reserved. */
+#define GCREG_BLOCK8_TRANSPARENCY_PATTERN                                  5 : 4
+#define GCREG_BLOCK8_TRANSPARENCY_PATTERN_End                                  5
+#define GCREG_BLOCK8_TRANSPARENCY_PATTERN_Start                                4
+#define GCREG_BLOCK8_TRANSPARENCY_PATTERN_Type                               U02
+#define   GCREG_BLOCK8_TRANSPARENCY_PATTERN_OPAQUE                           0x0
+#define   GCREG_BLOCK8_TRANSPARENCY_PATTERN_MASK                             0x1
+#define   GCREG_BLOCK8_TRANSPARENCY_PATTERN_KEY                              0x2
+
+/* Destination transparency mode. MASK transparency mode is reserved. */
+#define GCREG_BLOCK8_TRANSPARENCY_DESTINATION                              9 : 8
+#define GCREG_BLOCK8_TRANSPARENCY_DESTINATION_End                              9
+#define GCREG_BLOCK8_TRANSPARENCY_DESTINATION_Start                            8
+#define GCREG_BLOCK8_TRANSPARENCY_DESTINATION_Type                           U02
+#define   GCREG_BLOCK8_TRANSPARENCY_DESTINATION_OPAQUE                       0x0
+#define   GCREG_BLOCK8_TRANSPARENCY_DESTINATION_MASK                         0x1
+#define   GCREG_BLOCK8_TRANSPARENCY_DESTINATION_KEY                          0x2
+
+/* Mask field for Source/Pattern/Destination fields. */
+#define GCREG_BLOCK8_TRANSPARENCY_MASK_TRANSPARENCY                      12 : 12
+#define GCREG_BLOCK8_TRANSPARENCY_MASK_TRANSPARENCY_End                       12
+#define GCREG_BLOCK8_TRANSPARENCY_MASK_TRANSPARENCY_Start                     12
+#define GCREG_BLOCK8_TRANSPARENCY_MASK_TRANSPARENCY_Type                     U01
+#define   GCREG_BLOCK8_TRANSPARENCY_MASK_TRANSPARENCY_ENABLED                0x0
+#define   GCREG_BLOCK8_TRANSPARENCY_MASK_TRANSPARENCY_MASKED                 0x1
+
+/* Source usage override. */
+#define GCREG_BLOCK8_TRANSPARENCY_USE_SRC_OVERRIDE                       17 : 16
+#define GCREG_BLOCK8_TRANSPARENCY_USE_SRC_OVERRIDE_End                        17
+#define GCREG_BLOCK8_TRANSPARENCY_USE_SRC_OVERRIDE_Start                      16
+#define GCREG_BLOCK8_TRANSPARENCY_USE_SRC_OVERRIDE_Type                      U02
+#define   GCREG_BLOCK8_TRANSPARENCY_USE_SRC_OVERRIDE_DEFAULT                 0x0
+#define   GCREG_BLOCK8_TRANSPARENCY_USE_SRC_OVERRIDE_USE_ENABLE              0x1
+#define   GCREG_BLOCK8_TRANSPARENCY_USE_SRC_OVERRIDE_USE_DISABLE             0x2
+
+/* Pattern usage override. */
+#define GCREG_BLOCK8_TRANSPARENCY_USE_PAT_OVERRIDE                       21 : 20
+#define GCREG_BLOCK8_TRANSPARENCY_USE_PAT_OVERRIDE_End                        21
+#define GCREG_BLOCK8_TRANSPARENCY_USE_PAT_OVERRIDE_Start                      20
+#define GCREG_BLOCK8_TRANSPARENCY_USE_PAT_OVERRIDE_Type                      U02
+#define   GCREG_BLOCK8_TRANSPARENCY_USE_PAT_OVERRIDE_DEFAULT                 0x0
+#define   GCREG_BLOCK8_TRANSPARENCY_USE_PAT_OVERRIDE_USE_ENABLE              0x1
+#define   GCREG_BLOCK8_TRANSPARENCY_USE_PAT_OVERRIDE_USE_DISABLE             0x2
+
+/* Destination usage override. */
+#define GCREG_BLOCK8_TRANSPARENCY_USE_DST_OVERRIDE                       25 : 24
+#define GCREG_BLOCK8_TRANSPARENCY_USE_DST_OVERRIDE_End                        25
+#define GCREG_BLOCK8_TRANSPARENCY_USE_DST_OVERRIDE_Start                      24
+#define GCREG_BLOCK8_TRANSPARENCY_USE_DST_OVERRIDE_Type                      U02
+#define   GCREG_BLOCK8_TRANSPARENCY_USE_DST_OVERRIDE_DEFAULT                 0x0
+#define   GCREG_BLOCK8_TRANSPARENCY_USE_DST_OVERRIDE_USE_ENABLE              0x1
+#define   GCREG_BLOCK8_TRANSPARENCY_USE_DST_OVERRIDE_USE_DISABLE             0x2
+
+/* 2D resource usage override mask field. */
+#define GCREG_BLOCK8_TRANSPARENCY_MASK_RESOURCE_OVERRIDE                 28 : 28
+#define GCREG_BLOCK8_TRANSPARENCY_MASK_RESOURCE_OVERRIDE_End                  28
+#define GCREG_BLOCK8_TRANSPARENCY_MASK_RESOURCE_OVERRIDE_Start                28
+#define GCREG_BLOCK8_TRANSPARENCY_MASK_RESOURCE_OVERRIDE_Type                U01
+#define   GCREG_BLOCK8_TRANSPARENCY_MASK_RESOURCE_OVERRIDE_ENABLED           0x0
+#define   GCREG_BLOCK8_TRANSPARENCY_MASK_RESOURCE_OVERRIDE_MASKED            0x1
+
+/* DFB Color Key. */
+#define GCREG_BLOCK8_TRANSPARENCY_DFB_COLOR_KEY                          29 : 29
+#define GCREG_BLOCK8_TRANSPARENCY_DFB_COLOR_KEY_End                           29
+#define GCREG_BLOCK8_TRANSPARENCY_DFB_COLOR_KEY_Start                         29
+#define GCREG_BLOCK8_TRANSPARENCY_DFB_COLOR_KEY_Type                         U01
+#define   GCREG_BLOCK8_TRANSPARENCY_DFB_COLOR_KEY_DISABLED                   0x0
+#define   GCREG_BLOCK8_TRANSPARENCY_DFB_COLOR_KEY_ENABLED                    0x1
+
+#define GCREG_BLOCK8_TRANSPARENCY_MASK_DFB_COLOR_KEY                     31 : 31
+#define GCREG_BLOCK8_TRANSPARENCY_MASK_DFB_COLOR_KEY_End                      31
+#define GCREG_BLOCK8_TRANSPARENCY_MASK_DFB_COLOR_KEY_Start                    31
+#define GCREG_BLOCK8_TRANSPARENCY_MASK_DFB_COLOR_KEY_Type                    U01
+#define   GCREG_BLOCK8_TRANSPARENCY_MASK_DFB_COLOR_KEY_ENABLED               0x0
+#define   GCREG_BLOCK8_TRANSPARENCY_MASK_DFB_COLOR_KEY_MASKED                0x1
+
+/*******************************************************************************
+** State gcregBlock8Control
+*/
+
+/* General purpose control register. */
+
+#define gcregBlock8PEControlRegAddrs                                      0x4B20
+#define GCREG_BLOCK8_PE_CONTROL_MSB                                           15
+#define GCREG_BLOCK8_PE_CONTROL_LSB                                            3
+#define GCREG_BLOCK8_PE_CONTROL_BLK                                            0
+#define GCREG_BLOCK8_PE_CONTROL_Count                                          8
+#define GCREG_BLOCK8_PE_CONTROL_FieldMask                             0x00000999
+#define GCREG_BLOCK8_PE_CONTROL_ReadMask                              0x00000999
+#define GCREG_BLOCK8_PE_CONTROL_WriteMask                             0x00000999
+#define GCREG_BLOCK8_PE_CONTROL_ResetValue                            0x00000000
+
+#define GCREG_BLOCK8_PE_CONTROL_YUV                                        0 : 0
+#define GCREG_BLOCK8_PE_CONTROL_YUV_End                                        0
+#define GCREG_BLOCK8_PE_CONTROL_YUV_Start                                      0
+#define GCREG_BLOCK8_PE_CONTROL_YUV_Type                                     U01
+#define   GCREG_BLOCK8_PE_CONTROL_YUV_601                                    0x0
+#define   GCREG_BLOCK8_PE_CONTROL_YUV_709                                    0x1
+
+#define GCREG_BLOCK8_PE_CONTROL_MASK_YUV                                   3 : 3
+#define GCREG_BLOCK8_PE_CONTROL_MASK_YUV_End                                   3
+#define GCREG_BLOCK8_PE_CONTROL_MASK_YUV_Start                                 3
+#define GCREG_BLOCK8_PE_CONTROL_MASK_YUV_Type                                U01
+#define   GCREG_BLOCK8_PE_CONTROL_MASK_YUV_ENABLED                           0x0
+#define   GCREG_BLOCK8_PE_CONTROL_MASK_YUV_MASKED                            0x1
+
+#define GCREG_BLOCK8_PE_CONTROL_UV_SWIZZLE                                 4 : 4
+#define GCREG_BLOCK8_PE_CONTROL_UV_SWIZZLE_End                                 4
+#define GCREG_BLOCK8_PE_CONTROL_UV_SWIZZLE_Start                               4
+#define GCREG_BLOCK8_PE_CONTROL_UV_SWIZZLE_Type                              U01
+#define   GCREG_BLOCK8_PE_CONTROL_UV_SWIZZLE_UV                              0x0
+#define   GCREG_BLOCK8_PE_CONTROL_UV_SWIZZLE_VU                              0x1
+
+#define GCREG_BLOCK8_PE_CONTROL_MASK_UV_SWIZZLE                            7 : 7
+#define GCREG_BLOCK8_PE_CONTROL_MASK_UV_SWIZZLE_End                            7
+#define GCREG_BLOCK8_PE_CONTROL_MASK_UV_SWIZZLE_Start                          7
+#define GCREG_BLOCK8_PE_CONTROL_MASK_UV_SWIZZLE_Type                         U01
+#define   GCREG_BLOCK8_PE_CONTROL_MASK_UV_SWIZZLE_ENABLED                    0x0
+#define   GCREG_BLOCK8_PE_CONTROL_MASK_UV_SWIZZLE_MASKED                     0x1
+
+/* YUV to RGB convert enable */
+#define GCREG_BLOCK8_PE_CONTROL_YUVRGB                                     8 : 8
+#define GCREG_BLOCK8_PE_CONTROL_YUVRGB_End                                     8
+#define GCREG_BLOCK8_PE_CONTROL_YUVRGB_Start                                   8
+#define GCREG_BLOCK8_PE_CONTROL_YUVRGB_Type                                  U01
+#define   GCREG_BLOCK8_PE_CONTROL_YUVRGB_DISABLED                            0x0
+#define   GCREG_BLOCK8_PE_CONTROL_YUVRGB_ENABLED                             0x1
+
+#define GCREG_BLOCK8_PE_CONTROL_MASK_YUVRGB                              11 : 11
+#define GCREG_BLOCK8_PE_CONTROL_MASK_YUVRGB_End                               11
+#define GCREG_BLOCK8_PE_CONTROL_MASK_YUVRGB_Start                             11
+#define GCREG_BLOCK8_PE_CONTROL_MASK_YUVRGB_Type                             U01
+#define   GCREG_BLOCK8_PE_CONTROL_MASK_YUVRGB_ENABLED                        0x0
+#define   GCREG_BLOCK8_PE_CONTROL_MASK_YUVRGB_MASKED                         0x1
+
+/*******************************************************************************
+** State gcregBlock8SrcColorKeyHigh
+*/
+
+/* Defines the source transparency color in source format. */
+
+#define gcregBlock8SrcColorKeyHighRegAddrs                                0x4B28
+#define GCREG_BLOCK8_SRC_COLOR_KEY_HIGH_MSB                                   15
+#define GCREG_BLOCK8_SRC_COLOR_KEY_HIGH_LSB                                    3
+#define GCREG_BLOCK8_SRC_COLOR_KEY_HIGH_BLK                                    0
+#define GCREG_BLOCK8_SRC_COLOR_KEY_HIGH_Count                                  8
+#define GCREG_BLOCK8_SRC_COLOR_KEY_HIGH_FieldMask                     0xFFFFFFFF
+#define GCREG_BLOCK8_SRC_COLOR_KEY_HIGH_ReadMask                      0xFFFFFFFF
+#define GCREG_BLOCK8_SRC_COLOR_KEY_HIGH_WriteMask                     0xFFFFFFFF
+#define GCREG_BLOCK8_SRC_COLOR_KEY_HIGH_ResetValue                    0x00000000
+
+#define GCREG_BLOCK8_SRC_COLOR_KEY_HIGH_ALPHA                            31 : 24
+#define GCREG_BLOCK8_SRC_COLOR_KEY_HIGH_ALPHA_End                             31
+#define GCREG_BLOCK8_SRC_COLOR_KEY_HIGH_ALPHA_Start                           24
+#define GCREG_BLOCK8_SRC_COLOR_KEY_HIGH_ALPHA_Type                           U08
+
+#define GCREG_BLOCK8_SRC_COLOR_KEY_HIGH_RED                              23 : 16
+#define GCREG_BLOCK8_SRC_COLOR_KEY_HIGH_RED_End                               23
+#define GCREG_BLOCK8_SRC_COLOR_KEY_HIGH_RED_Start                             16
+#define GCREG_BLOCK8_SRC_COLOR_KEY_HIGH_RED_Type                             U08
+
+#define GCREG_BLOCK8_SRC_COLOR_KEY_HIGH_GREEN                             15 : 8
+#define GCREG_BLOCK8_SRC_COLOR_KEY_HIGH_GREEN_End                             15
+#define GCREG_BLOCK8_SRC_COLOR_KEY_HIGH_GREEN_Start                            8
+#define GCREG_BLOCK8_SRC_COLOR_KEY_HIGH_GREEN_Type                           U08
+
+#define GCREG_BLOCK8_SRC_COLOR_KEY_HIGH_BLUE                               7 : 0
+#define GCREG_BLOCK8_SRC_COLOR_KEY_HIGH_BLUE_End                               7
+#define GCREG_BLOCK8_SRC_COLOR_KEY_HIGH_BLUE_Start                             0
+#define GCREG_BLOCK8_SRC_COLOR_KEY_HIGH_BLUE_Type                            U08
+
+/*******************************************************************************
+** State gcregBlock8SrcExConfig
+*/
+
+#define gcregBlock8SrcExConfigRegAddrs                                    0x4B30
+#define GCREG_BLOCK8_SRC_EX_CONFIG_MSB                                        15
+#define GCREG_BLOCK8_SRC_EX_CONFIG_LSB                                         3
+#define GCREG_BLOCK8_SRC_EX_CONFIG_BLK                                         0
+#define GCREG_BLOCK8_SRC_EX_CONFIG_Count                                       8
+#define GCREG_BLOCK8_SRC_EX_CONFIG_FieldMask                          0x00000109
+#define GCREG_BLOCK8_SRC_EX_CONFIG_ReadMask                           0x00000109
+#define GCREG_BLOCK8_SRC_EX_CONFIG_WriteMask                          0x00000109
+#define GCREG_BLOCK8_SRC_EX_CONFIG_ResetValue                         0x00000000
+
+/* Source multi tiled address computation control. */
+#define GCREG_BLOCK8_SRC_EX_CONFIG_MULTI_TILED                             0 : 0
+#define GCREG_BLOCK8_SRC_EX_CONFIG_MULTI_TILED_End                             0
+#define GCREG_BLOCK8_SRC_EX_CONFIG_MULTI_TILED_Start                           0
+#define GCREG_BLOCK8_SRC_EX_CONFIG_MULTI_TILED_Type                          U01
+#define   GCREG_BLOCK8_SRC_EX_CONFIG_MULTI_TILED_DISABLED                    0x0
+#define   GCREG_BLOCK8_SRC_EX_CONFIG_MULTI_TILED_ENABLED                     0x1
+
+/* Source super tiled address computation control. */
+#define GCREG_BLOCK8_SRC_EX_CONFIG_SUPER_TILED                             3 : 3
+#define GCREG_BLOCK8_SRC_EX_CONFIG_SUPER_TILED_End                             3
+#define GCREG_BLOCK8_SRC_EX_CONFIG_SUPER_TILED_Start                           3
+#define GCREG_BLOCK8_SRC_EX_CONFIG_SUPER_TILED_Type                          U01
+#define   GCREG_BLOCK8_SRC_EX_CONFIG_SUPER_TILED_DISABLED                    0x0
+#define   GCREG_BLOCK8_SRC_EX_CONFIG_SUPER_TILED_ENABLED                     0x1
+
+/* Source super tiled address computation control. */
+#define GCREG_BLOCK8_SRC_EX_CONFIG_MINOR_TILED                             8 : 8
+#define GCREG_BLOCK8_SRC_EX_CONFIG_MINOR_TILED_End                             8
+#define GCREG_BLOCK8_SRC_EX_CONFIG_MINOR_TILED_Start                           8
+#define GCREG_BLOCK8_SRC_EX_CONFIG_MINOR_TILED_Type                          U01
+#define   GCREG_BLOCK8_SRC_EX_CONFIG_MINOR_TILED_DISABLED                    0x0
+#define   GCREG_BLOCK8_SRC_EX_CONFIG_MINOR_TILED_ENABLED                     0x1
+
+/* Source CacheMode. */
+#define GCREG_BLOCK8_SRC_EX_CONFIG_CACHE_MODE                            12 : 12
+#define GCREG_BLOCK8_SRC_EX_CONFIG_CACHE_MODE_End                             12
+#define GCREG_BLOCK8_SRC_EX_CONFIG_CACHE_MODE_Start                           12
+#define GCREG_BLOCK8_SRC_EX_CONFIG_CACHE_MODE_Type                           U01
+#define   GCREG_BLOCK8_SRC_EX_CONFIG_CACHE_MODE_DISABLED                     0x0
+#define   GCREG_BLOCK8_SRC_EX_CONFIG_CACHE_MODE_ENABLED                      0x1
+
+/*******************************************************************************
+** State gcregBlock8SrcExAddress
+*/
+
+/* 32-bit aligned base address of the source extra surface. */
+
+#define gcregBlock8SrcExAddressRegAddrs                                   0x4B38
+#define GCREG_BLOCK8_SRC_EX_ADDRESS_MSB                                       15
+#define GCREG_BLOCK8_SRC_EX_ADDRESS_LSB                                        3
+#define GCREG_BLOCK8_SRC_EX_ADDRESS_BLK                                        0
+#define GCREG_BLOCK8_SRC_EX_ADDRESS_Count                                      8
+#define GCREG_BLOCK8_SRC_EX_ADDRESS_FieldMask                         0xFFFFFFFF
+#define GCREG_BLOCK8_SRC_EX_ADDRESS_ReadMask                          0xFFFFFFFC
+#define GCREG_BLOCK8_SRC_EX_ADDRESS_WriteMask                         0xFFFFFFFC
+#define GCREG_BLOCK8_SRC_EX_ADDRESS_ResetValue                        0x00000000
+
+#define GCREG_BLOCK8_SRC_EX_ADDRESS_ADDRESS                               31 : 0
+#define GCREG_BLOCK8_SRC_EX_ADDRESS_ADDRESS_End                               30
+#define GCREG_BLOCK8_SRC_EX_ADDRESS_ADDRESS_Start                              0
+#define GCREG_BLOCK8_SRC_EX_ADDRESS_ADDRESS_Type                             U31
+
+/*******************************************************************************
+** Generic defines
+*/
+
+#define GCREG_FORMAT_SUB_SAMPLE_MODE_YUV_MODE422                             0x0
+#define GCREG_FORMAT_SUB_SAMPLE_MODE_YUV_MODE420                             0x1
+
+#define GCREG_DE_SWIZZLE_ARGB                                                0x0
+#define GCREG_DE_SWIZZLE_RGBA                                                0x1
+#define GCREG_DE_SWIZZLE_ABGR                                                0x2
+#define GCREG_DE_SWIZZLE_BGRA                                                0x3
+
+#define GCREG_DE_FORMAT_X4R4G4B4                                            0x00
+#define GCREG_DE_FORMAT_A4R4G4B4                                            0x01
+#define GCREG_DE_FORMAT_X1R5G5B5                                            0x02
+#define GCREG_DE_FORMAT_A1R5G5B5                                            0x03
+#define GCREG_DE_FORMAT_R5G6B5                                              0x04
+#define GCREG_DE_FORMAT_X8R8G8B8                                            0x05
+#define GCREG_DE_FORMAT_A8R8G8B8                                            0x06
+#define GCREG_DE_FORMAT_YUY2                                                0x07
+#define GCREG_DE_FORMAT_UYVY                                                0x08
+#define GCREG_DE_FORMAT_INDEX8                                              0x09
+#define GCREG_DE_FORMAT_MONOCHROME                                          0x0A
+#define GCREG_DE_FORMAT_YV12                                                0x0F
+#define GCREG_DE_FORMAT_A8                                                  0x10
+#define GCREG_DE_FORMAT_NV12                                                0x11
+#define GCREG_DE_FORMAT_NV16                                                0x12
+#define GCREG_DE_FORMAT_RG16                                                0x13
+
+/* ~~~~~~~~~~~~~ */
+
+#define GCREG_ALPHA_MODE_NORMAL                                              0x0
+#define GCREG_ALPHA_MODE_INVERSED                                            0x1
+
+#define GCREG_GLOBAL_ALPHA_MODE_NORMAL                                       0x0
+#define GCREG_GLOBAL_ALPHA_MODE_GLOBAL                                       0x1
+#define GCREG_GLOBAL_ALPHA_MODE_SCALED                                       0x2
+
+#define GCREG_COLOR_MODE_NORMAL                                              0x0
+#define GCREG_COLOR_MODE_MULTIPLY                                            0x1
+
+#define GCREG_BLENDING_MODE_ZERO                                             0x0
+#define GCREG_BLENDING_MODE_ONE                                              0x1
+#define GCREG_BLENDING_MODE_NORMAL                                           0x2
+#define GCREG_BLENDING_MODE_INVERSED                                         0x3
+#define GCREG_BLENDING_MODE_COLOR                                            0x4
+#define GCREG_BLENDING_MODE_COLOR_INVERSED                                   0x5
+#define GCREG_BLENDING_MODE_SATURATED_ALPHA                                  0x6
+#define GCREG_BLENDING_MODE_SATURATED_DEST_ALPHA                             0x7
+
+#define GCREG_SRC_GLOBAL_PREMULTIPLY_DISABLE                                 0x0
+#define GCREG_SRC_GLOBAL_PREMULTIPLY_ALPHA                                   0x1
+#define GCREG_SRC_GLOBAL_PREMULTIPLY_COLOR                                   0x2
+
+/* ~~~~~~~~~~~~~ */
+
+#define GCREG_FACTOR_INVERSE_DISABLE                                         0x0
+#define GCREG_FACTOR_INVERSE_ENABLE                                          0x1
+
+/* ~~~~~~~~~~~~~ */
+
+#define GCREG_RESOURCE_USAGE_OVERRIDE_DEFAULT                                0x0
+#define GCREG_RESOURCE_USAGE_OVERRIDE_USE_ENABLE                             0x1
+#define GCREG_RESOURCE_USAGE_OVERRIDE_USE_DISABLE                            0x2
+
+/*******************************************************************************
+** Modular operations: pipesel
+*/
+
+static const struct gccmdldstate gcmopipesel_pipesel_ldst =
+	GCLDSTATE(gcregPipeSelectRegAddrs, 1);
+
+struct gcmopipesel {
+	/* gcregPipeSelectRegAddrs */
+	struct gccmdldstate pipesel_ldst;
+
+		/* gcregPipeSelectRegAddrs */
+		union {
+			struct gcregpipeselect reg;
+			unsigned int raw;
+		} pipesel;
+};
+
+/*******************************************************************************
+** Modular operations: signal
+*/
+
+static const struct gccmdldstate gcmosignal_signal_ldst =
+	GCLDSTATE(gcregEventRegAddrs, 1);
+
+struct gcmosignal {
+	/* gcregEventRegAddrs */
+	struct gccmdldstate signal_ldst;
+
+		/* gcregEventRegAddrs */
+		union {
+			struct gcregevent reg;
+			unsigned int raw;
+		} signal;
+};
+
+/*******************************************************************************
+** Modular operations: flush
+*/
+
+static const struct gccmdldstate gcmoflush_flush_ldst =
+	GCLDSTATE(gcregFlushRegAddrs, 1);
+
+struct gcmoflush {
+	/* gcregFlushRegAddrs */
+	struct gccmdldstate flush_ldst;
+
+		/* gcregFlushRegAddrs */
+		union {
+			struct gcregflush reg;
+			unsigned int raw;
+		} flush;
+};
+
+/*******************************************************************************
+** Modular operations: semaphore
+*/
+
+static const struct gccmdldstate gcmosema_sema_ldst =
+	GCLDSTATE(gcregSemaphoreRegAddrs, 1);
+
+struct gcmosema {
+	/* gcregSemaphoreRegAddrs */
+	struct gccmdldstate sema_ldst;
+
+		/* gcregSemaphoreRegAddrs */
+		union {
+			struct gcregsemaphore reg;
+			unsigned int raw;
+		} sema;
+};
+
+/*******************************************************************************
+** Modular operations: mmuinit
+*/
+
+struct gcmoterminator {
+	union {
+		struct gcmosignal done;
+		struct gccmdnop nop;
+	} u1;
+
+	union {
+		struct gccmdwait wait;
+		struct gccmdlink linknext;
+		struct gccmdend end;
+	} u2;
+
+	union {
+		struct gccmdlink linkwait;
+		struct gccmdnop nop;
+	} u3;
+};
+
+/*******************************************************************************
+** Modular operations: mmuinit
+*/
+
+static const struct gccmdldstate gcmommuinit_safe_ldst =
+	GCLDSTATE(gcregMMUSafeAddressRegAddrs, 2);
+
+struct gcmommuinit {
+	/* gcregMMUSafeAddressRegAddrs */
+	struct gccmdldstate safe_ldst;
+
+		/* gcregMMUSafeAddressRegAddrs */
+		unsigned int safe;
+
+		/* gcregMMUConfigurationRegAddrs */
+		unsigned int mtlb;
+
+		/* Alignment filler. */
+		unsigned int _filler;
+};
+
+/*******************************************************************************
+** Modular operations: mmumaster
+*/
+
+static const struct gccmdldstate gcmommumaster_master_ldst =
+	GCLDSTATE(gcregMMUConfigurationRegAddrs, 1);
+
+struct gcmommumaster {
+	/* gcregMMUConfigurationRegAddrs */
+	struct gccmdldstate master_ldst;
+
+		/* gcregMMUConfigurationRegAddrs */
+		unsigned int master;
+};
+
+/*******************************************************************************
+** Modular operations: mmuflush
+*/
+
+static const struct gccmdldstate gcmommuflush_mmuflush_ldst =
+	GCLDSTATE(gcregMMUConfigurationRegAddrs, 1);
+
+struct gcmommuflush {
+	/* PE cache flush. */
+	struct gcmoflush peflush;
+
+	/* Semaphore/stall after PE flush. */
+	struct gcmosema peflushsema;
+	struct gccmdstall peflushstall;
+
+	/* Link to flush FE FIFO. */
+	struct gccmdlink feflush;
+
+	/* MMU flush. */
+	struct gccmdldstate mmuflush_ldst;
+
+		/* gcregMMUConfigurationRegAddrs */
+		union {
+			struct gcregmmuconfiguration reg;
+			unsigned int raw;
+		} mmuflush;
+
+	/* Semaphore/stall after MMU flush. */
+	struct gcmosema mmuflushsema;
+	struct gccmdstall mmuflushstall;
+
+	/* Link to the user buffer. */
+	struct gccmdlink link;
+};
+
+/*******************************************************************************
+** Modular operations: dst
+*/
+
+static const struct gccmdldstate gcmodst_config_ldst =
+	GCLDSTATE(gcregDestAddressRegAddrs, 3);
+
+static const struct gccmdldstate gcmodst_rotationheight_ldst =
+	GCLDSTATE(gcregDstRotationHeightRegAddrs, 1);
+
+static const struct gccmdldstate gcmodst_clip_ldst =
+	GCLDSTATE(gcregClipTopLeftRegAddrs, 2);
+
+struct gcmodst {
+	/* Configuration block. */
+	struct gccmdldstate config_ldst;
+
+		/* gcregDestAddressRegAddrs */
+		unsigned int address;
+
+		/* gcregDestStrideRegAddrs */
+		unsigned int stride;
+
+		/* gcregDestRotationConfigRegAddrs */
+		union {
+			struct gcregdstrotationconfig reg;
+			unsigned int raw;
+		} rotation;
+
+	/* gcregDstRotationHeightRegAddrs */
+	struct gccmdldstate rotationheight_ldst;
+
+		/* gcregDstRotationHeightRegAddrs */
+		union {
+			struct gcregdstrotationheight reg;
+			unsigned int raw;
+		} rotationheight;
+
+	/* Clipping block. */
+	struct gccmdldstate clip_ldst;
+
+		/* gcregClipTopLeftRegAddrs */
+		union {
+			struct gcregcliplt reg;
+			unsigned int raw;
+		} cliplt;
+
+		/* gcregClipBottomRight */
+		union {
+			struct gcregcliprb reg;
+			unsigned int raw;
+		} cliprb;
+
+		/* Alignment filler. */
+		unsigned int _filler;
+};
+
+/*******************************************************************************
+** Modular operations: alphaoff
+*/
+
+static const struct gccmdldstate gcmoalphaoff_control_ldst[8] = {
+	GCLDSTATE(gcregAlphaControlRegAddrs, 1),
+	GCLDSTATE(gcregBlock4AlphaControlRegAddrs + 1, 1),
+	GCLDSTATE(gcregBlock4AlphaControlRegAddrs + 2, 1),
+	GCLDSTATE(gcregBlock4AlphaControlRegAddrs + 3, 1),
+	GCLDSTATE(gcregBlock8AlphaControlRegAddrs + 4, 1),
+	GCLDSTATE(gcregBlock8AlphaControlRegAddrs + 5, 1),
+	GCLDSTATE(gcregBlock8AlphaControlRegAddrs + 6, 1),
+	GCLDSTATE(gcregBlock8AlphaControlRegAddrs + 7, 1)
+};
+
+struct gcmoalphaoff {
+	/* gcregAlphaControlRegAddrs */
+	struct gccmdldstate control_ldst;
+
+		/* gcregAlphaControlRegAddrs */
+		union {
+			struct gcregalphacontrol reg;
+			unsigned int raw;
+		} control;
+};
+
+/*******************************************************************************
+** Modular operations: alpha
+*/
+
+static const struct gccmdldstate gcmoalpha_config_ldst =
+	GCLDSTATE(gcregAlphaControlRegAddrs, 2);
+
+struct gcmoalpha {
+	/* Alpha control block. */
+	struct gccmdldstate config_ldst;
+
+		/* gcregAlphaControlRegAddrs */
+		union {
+			struct gcregalphacontrol reg;
+			unsigned int raw;
+		} control;
+
+		/* gcregAlphaModesRegAddrs */
+		union {
+			struct gcregalphamodes reg;
+			unsigned int raw;
+		} mode;
+
+		/* Alignment filler. */
+		unsigned int _filler;
+};
+
+static const struct gccmdldstate gcmoxsrcalpha_control_ldst[8] = {
+	GCLDSTATE(gcregAlphaControlRegAddrs, 1),
+	GCLDSTATE(gcregBlock4AlphaControlRegAddrs + 1, 1),
+	GCLDSTATE(gcregBlock4AlphaControlRegAddrs + 2, 1),
+	GCLDSTATE(gcregBlock4AlphaControlRegAddrs + 3, 1),
+	GCLDSTATE(gcregBlock8AlphaControlRegAddrs + 4, 1),
+	GCLDSTATE(gcregBlock8AlphaControlRegAddrs + 5, 1),
+	GCLDSTATE(gcregBlock8AlphaControlRegAddrs + 6, 1),
+	GCLDSTATE(gcregBlock8AlphaControlRegAddrs + 7, 1)
+};
+
+static const struct gccmdldstate gcmoxsrcalpha_mode_ldst[8] = {
+	GCLDSTATE(gcregAlphaModesRegAddrs, 1),
+	GCLDSTATE(gcregBlock4AlphaModesRegAddrs + 1, 1),
+	GCLDSTATE(gcregBlock4AlphaModesRegAddrs + 2, 1),
+	GCLDSTATE(gcregBlock4AlphaModesRegAddrs + 3, 1),
+	GCLDSTATE(gcregBlock8AlphaModesRegAddrs + 4, 1),
+	GCLDSTATE(gcregBlock8AlphaModesRegAddrs + 5, 1),
+	GCLDSTATE(gcregBlock8AlphaModesRegAddrs + 6, 1),
+	GCLDSTATE(gcregBlock8AlphaModesRegAddrs + 7, 1)
+};
+
+struct gcmoxsrcalpha {
+	/* gcregBlock4AlphaControlRegAddrs */
+	struct gccmdldstate control_ldst;
+
+		/* gcregBlock4AlphaControlRegAddrs */
+		union {
+			struct gcregalphacontrol reg;
+			unsigned int raw;
+		} control;
+
+	/* gcregBlock4AlphaModesRegAddrs */
+	struct gccmdldstate mode_ldst;
+
+		/* gcregBlock4AlphaModesRegAddrs */
+		union {
+			struct gcregalphamodes reg;
+			unsigned int raw;
+		} mode;
+};
+
+/*******************************************************************************
+** Modular operations: alphaglobal
+*/
+
+static const struct gccmdldstate gcmoglobal_color_ldst =
+	GCLDSTATE(gcregGlobalSrcColorRegAddrs, 2);
+
+struct gcmoglobal {
+	/* Global color block. */
+	struct gccmdldstate color_ldst;
+
+		/* gcregGlobalSrcColorRegAddrs */
+		union {
+			struct gcregglobalsrccolor reg;
+			unsigned int raw;
+		} srcglobal;
+
+		/* gcregGlobalDestColorRegAddrs */
+		union {
+			struct gcregglobaldstcolor reg;
+			unsigned int raw;
+		} dstglobal;
+
+		/* Alignment filler. */
+		unsigned int _filler;
+};
+
+static const struct gccmdldstate gcmoxsrcglobal_srcglobal_ldst[8] = {
+	GCLDSTATE(gcregGlobalSrcColorRegAddrs, 1),
+	GCLDSTATE(gcregBlock4GlobalSrcColorRegAddrs + 1, 1),
+	GCLDSTATE(gcregBlock4GlobalSrcColorRegAddrs + 2, 1),
+	GCLDSTATE(gcregBlock4GlobalSrcColorRegAddrs + 3, 1),
+	GCLDSTATE(gcregBlock8GlobalSrcColorRegAddrs + 4, 1),
+	GCLDSTATE(gcregBlock8GlobalSrcColorRegAddrs + 5, 1),
+	GCLDSTATE(gcregBlock8GlobalSrcColorRegAddrs + 6, 1),
+	GCLDSTATE(gcregBlock8GlobalSrcColorRegAddrs + 7, 1)
+};
+
+static const struct gccmdldstate gcmoxsrcglobal_dstglobal_ldst[8] = {
+	GCLDSTATE(gcregGlobalDestColorRegAddrs, 1),
+	GCLDSTATE(gcregBlock4GlobalDestColorRegAddrs + 1, 1),
+	GCLDSTATE(gcregBlock4GlobalDestColorRegAddrs + 2, 1),
+	GCLDSTATE(gcregBlock4GlobalDestColorRegAddrs + 3, 1),
+	GCLDSTATE(gcregBlock8GlobalDestColorRegAddrs + 4, 1),
+	GCLDSTATE(gcregBlock8GlobalDestColorRegAddrs + 5, 1),
+	GCLDSTATE(gcregBlock8GlobalDestColorRegAddrs + 6, 1),
+	GCLDSTATE(gcregBlock8GlobalDestColorRegAddrs + 7, 1)
+};
+
+struct gcmoxsrcglobal {
+	/* gcregBlock4GlobalSrcColorRegAddrs */
+	struct gccmdldstate srcglobal_ldst;
+
+		/* gcregBlock4GlobalSrcColorRegAddrs */
+		union {
+			struct gcregglobalsrccolor reg;
+			unsigned int raw;
+		} srcglobal;
+
+	/* gcregBlock4GlobalDestColorRegAddrs */
+	struct gccmdldstate dstglobal_ldst;
+
+		/* gcregBlock4GlobalDestColorRegAddrs */
+		union {
+			struct gcregglobaldstcolor reg;
+			unsigned int raw;
+		} dstglobal;
+};
+
+/*******************************************************************************
+** Modular operations: yuv
+*/
+
+static const struct gccmdldstate gcmoyuv_pectrl_ldst =
+	GCLDSTATE(gcregPEControlRegAddrs, 1);
+
+static const struct gccmdldstate gcmoyuv2_plane_ldst =
+	GCLDSTATE(gcregUPlaneAddressRegAddrs, 2);
+
+static const struct gccmdldstate gcmoyuv3_plane_ldst =
+	GCLDSTATE(gcregUPlaneAddressRegAddrs, 4);
+
+struct gcmoyuv1 {
+	/* gcregPEControlRegAddrs */
+	struct gccmdldstate pectrl_ldst;
+
+		/* gcregPEControlRegAddrs */
+		union {
+			struct gcregpecontrol reg;
+			unsigned int raw;
+		} pectrl;
+};
+
+struct gcmoyuv2 {
+	/* gcregPEControlRegAddrs */
+	struct gccmdldstate pectrl_ldst;
+
+		/* gcregPEControlRegAddrs */
+		union {
+			struct gcregpecontrol reg;
+			unsigned int raw;
+		} pectrl;
+
+	/* Plane state block. */
+	struct gccmdldstate plane_ldst;
+
+		/* gcregUPlaneAddressRegAddrs */
+		unsigned int uplaneaddress;
+
+		/* gcregUPlaneStrideRegAddrs */
+		unsigned int uplanestride;
+
+		/* Alignment filler. */
+		unsigned int _filler1;
+};
+
+struct gcmoyuv3 {
+	/* gcregPEControlRegAddrs */
+	struct gccmdldstate pectrl_ldst;
+
+		/* gcregPEControlRegAddrs */
+		union {
+			struct gcregpecontrol reg;
+			unsigned int raw;
+		} pectrl;
+
+	/* Plane state block. */
+	struct gccmdldstate plane_ldst;
+
+		/* gcregUPlaneAddressRegAddrs */
+		unsigned int uplaneaddress;
+
+		/* gcregUPlaneStrideRegAddrs */
+		unsigned int uplanestride;
+
+		/* gcregVPlaneAddressRegAddrs */
+		unsigned int vplaneaddress;
+
+		/* gcregVPlaneStrideRegAddrs */
+		unsigned int vplanestride;
+
+		/* Alignment filler. */
+		unsigned int _filler1;
+};
+
+/*******************************************************************************
+** Modular operations: xsrcyuv
+*/
+
+static const struct gccmdldstate gcmoxsrcyuv_uplaneaddress_ldst[8] = {
+	GCLDSTATE(gcregUPlaneAddressRegAddrs, 1),
+	GCLDSTATE(gcregBlock4UPlaneAddressRegAddrs + 1, 1),
+	GCLDSTATE(gcregBlock4UPlaneAddressRegAddrs + 2, 1),
+	GCLDSTATE(gcregBlock4UPlaneAddressRegAddrs + 3, 1),
+	GCLDSTATE(gcregBlock8UPlaneAddressRegAddrs + 4, 1),
+	GCLDSTATE(gcregBlock8UPlaneAddressRegAddrs + 5, 1),
+	GCLDSTATE(gcregBlock8UPlaneAddressRegAddrs + 6, 1),
+	GCLDSTATE(gcregBlock8UPlaneAddressRegAddrs + 7, 1)
+};
+
+static const struct gccmdldstate gcmoxsrcyuv_uplanestride_ldst[8] = {
+	GCLDSTATE(gcregUPlaneStrideRegAddrs, 1),
+	GCLDSTATE(gcregBlock4UPlaneStrideRegAddrs + 1, 1),
+	GCLDSTATE(gcregBlock4UPlaneStrideRegAddrs + 2, 1),
+	GCLDSTATE(gcregBlock4UPlaneStrideRegAddrs + 3, 1),
+	GCLDSTATE(gcregBlock8UPlaneStrideRegAddrs + 4, 1),
+	GCLDSTATE(gcregBlock8UPlaneStrideRegAddrs + 5, 1),
+	GCLDSTATE(gcregBlock8UPlaneStrideRegAddrs + 6, 1),
+	GCLDSTATE(gcregBlock8UPlaneStrideRegAddrs + 7, 1)
+};
+
+static const struct gccmdldstate gcmoxsrcyuv_vplaneaddress_ldst[8] = {
+	GCLDSTATE(gcregVPlaneAddressRegAddrs, 1),
+	GCLDSTATE(gcregBlock4VPlaneAddressRegAddrs + 1, 1),
+	GCLDSTATE(gcregBlock4VPlaneAddressRegAddrs + 2, 1),
+	GCLDSTATE(gcregBlock4VPlaneAddressRegAddrs + 3, 1),
+	GCLDSTATE(gcregBlock8VPlaneAddressRegAddrs + 4, 1),
+	GCLDSTATE(gcregBlock8VPlaneAddressRegAddrs + 5, 1),
+	GCLDSTATE(gcregBlock8VPlaneAddressRegAddrs + 6, 1),
+	GCLDSTATE(gcregBlock8VPlaneAddressRegAddrs + 7, 1)
+};
+
+static const struct gccmdldstate gcmoxsrcyuv_vplanestride_ldst[8] = {
+	GCLDSTATE(gcregVPlaneStrideRegAddrs, 1),
+	GCLDSTATE(gcregBlock4VPlaneStrideRegAddrs + 1, 1),
+	GCLDSTATE(gcregBlock4VPlaneStrideRegAddrs + 2, 1),
+	GCLDSTATE(gcregBlock4VPlaneStrideRegAddrs + 3, 1),
+	GCLDSTATE(gcregBlock8VPlaneStrideRegAddrs + 4, 1),
+	GCLDSTATE(gcregBlock8VPlaneStrideRegAddrs + 5, 1),
+	GCLDSTATE(gcregBlock8VPlaneStrideRegAddrs + 6, 1),
+	GCLDSTATE(gcregBlock8VPlaneStrideRegAddrs + 7, 1)
+};
+
+static const struct gccmdldstate gcmoxsrcyuv_pectrl_ldst[8] = {
+	GCLDSTATE(gcregPEControlRegAddrs, 1),
+	GCLDSTATE(gcregBlock4PEControlRegAddrs + 1, 1),
+	GCLDSTATE(gcregBlock4PEControlRegAddrs + 2, 1),
+	GCLDSTATE(gcregBlock4PEControlRegAddrs + 3, 1),
+	GCLDSTATE(gcregBlock8PEControlRegAddrs + 4, 1),
+	GCLDSTATE(gcregBlock8PEControlRegAddrs + 5, 1),
+	GCLDSTATE(gcregBlock8PEControlRegAddrs + 6, 1),
+	GCLDSTATE(gcregBlock8PEControlRegAddrs + 7, 1)
+};
+
+struct gcmoxsrcyuv1 {
+	/* gcregBlock4PEControlRegAddrs */
+	struct gccmdldstate pectrl_ldst;
+
+		/* gcregBlock4PEControlRegAddrs */
+		union {
+			struct gcregpecontrol reg;
+			unsigned int raw;
+		} pectrl;
+};
+
+struct gcmoxsrcyuv2 {
+	/* gcregBlock4PEControlRegAddrs */
+	struct gccmdldstate pectrl_ldst;
+
+		/* gcregBlock4PEControlRegAddrs */
+		union {
+			struct gcregpecontrol reg;
+			unsigned int raw;
+		} pectrl;
+
+	/* gcregBlock4UPlaneAddressRegAddrs */
+	struct gccmdldstate uplaneaddress_ldst;
+
+		/* gcregBlock4UPlaneAddressRegAddrs */
+		unsigned int uplaneaddress;
+
+	/* gcregBlock4UPlaneStrideRegAddrs */
+	struct gccmdldstate uplanestride_ldst;
+
+		/* gcregBlock4UPlaneStrideRegAddrs */
+		unsigned int uplanestride;
+};
+
+struct gcmoxsrcyuv3 {
+	/* gcregBlock4PEControlRegAddrs */
+	struct gccmdldstate pectrl_ldst;
+
+		/* gcregBlock4PEControlRegAddrs */
+		union {
+			struct gcregpecontrol reg;
+			unsigned int raw;
+		} pectrl;
+
+	/* gcregBlock4UPlaneAddressRegAddrs */
+	struct gccmdldstate uplaneaddress_ldst;
+
+		/* gcregBlock4UPlaneAddressRegAddrs */
+		unsigned int uplaneaddress;
+
+	/* gcregBlock4UPlaneStrideRegAddrs */
+	struct gccmdldstate uplanestride_ldst;
+
+		/* gcregBlock4UPlaneStrideRegAddrs */
+		unsigned int uplanestride;
+
+	/* gcregBlock4VPlaneAddressRegAddrs */
+	struct gccmdldstate vplaneaddress_ldst;
+
+		/* gcregBlock4VPlaneAddressRegAddrs */
+		unsigned int vplaneaddress;
+
+	/* gcregBlock4VPlaneStrideRegAddrs */
+	struct gccmdldstate vplanestride_ldst;
+
+		/* gcregBlock4VPlaneStrideRegAddrs */
+		unsigned int vplanestride;
+};
+
+/*******************************************************************************
+** Modular operations: src
+*/
+
+static const struct gccmdldstate gcmosrc0_config_ldst =
+	GCLDSTATE(gcregSrcAddressRegAddrs, 6);
+
+static const struct gccmdldstate gcmosrc0_rotation_ldst =
+	GCLDSTATE(gcregSrcRotationHeightRegAddrs, 2);
+
+static const struct gccmdldstate gcmosrc0_rop_ldst =
+	GCLDSTATE(gcregRopRegAddrs, 1);
+
+static const struct gccmdldstate gcmosrc0_mult_ldst =
+	GCLDSTATE(gcregColorMultiplyModesRegAddrs, 1);
+
+struct gcmosrc0 {
+	/* Configuration block. */
+	struct gccmdldstate config_ldst;
+
+		/* gcregSrcAddressRegAddrs */
+		unsigned int address;
+
+		/* gcregSrcStrideRegAddrs */
+		unsigned int stride;
+
+		/* gcregSrcRotationConfigRegAddrs */
+		union {
+			struct gcregsrcrotationconfig reg;
+			unsigned int raw;
+		} rotation;
+
+		/* gcregSrcConfigRegAddrs */
+		union {
+			struct gcregsrcconfig reg;
+			unsigned int raw;
+		} config;
+
+		/* gcregSrcOriginRegAddrs */
+		union {
+			struct gcregsrcorigin reg;
+			unsigned int raw;
+		} origin;
+
+		/* gcregSrcSizeRegAddrs */
+		union {
+			struct gcregsrcsize reg;
+			unsigned int raw;
+		} size;
+
+		/* Alignment filler. */
+		unsigned int _filler1;
+
+	/* Rotation block. */
+	struct gccmdldstate rotation_ldst;
+
+		/* gcregSrcRotationHeightRegAddrs */
+		union {
+			struct gcregsrcrotationheight reg;
+			unsigned int raw;
+		} rotationheight;
+
+		/* gcregRotAngleRegAddrs */
+		union {
+			struct gcregrotangle reg;
+			unsigned int raw;
+		} rotationangle;
+
+		/* Alignment filler. */
+		unsigned int _filler2;
+
+	/* gcregRopRegAddrs */
+	struct gccmdldstate rop_ldst;
+
+		/* gcregRopRegAddrs */
+		union {
+			struct gcregrop reg;
+			unsigned int raw;
+		} rop;
+
+	/* gcregColorMultiplyModesRegAddrs */
+	struct gccmdldstate mult_ldst;
+
+		/* gcregColorMultiplyModesRegAddrs */
+		union {
+			struct gcregcolormultiplymodes reg;
+			unsigned int raw;
+		} mult;
+};
+
+static const struct gccmdldstate gcmosrc_address_ldst[8] = {
+	GCLDSTATE(gcregSrcAddressRegAddrs, 1),
+	GCLDSTATE(gcregBlock4SrcAddressRegAddrs + 1, 1),
+	GCLDSTATE(gcregBlock4SrcAddressRegAddrs + 2, 1),
+	GCLDSTATE(gcregBlock4SrcAddressRegAddrs + 3, 1),
+	GCLDSTATE(gcregBlock8SrcAddressRegAddrs + 4, 1),
+	GCLDSTATE(gcregBlock8SrcAddressRegAddrs + 5, 1),
+	GCLDSTATE(gcregBlock8SrcAddressRegAddrs + 6, 1),
+	GCLDSTATE(gcregBlock8SrcAddressRegAddrs + 7, 1)
+};
+
+static const struct gccmdldstate gcmosrc_stride_ldst[8] = {
+	GCLDSTATE(gcregSrcStrideRegAddrs, 1),
+	GCLDSTATE(gcregBlock4SrcStrideRegAddrs + 1, 1),
+	GCLDSTATE(gcregBlock4SrcStrideRegAddrs + 2, 1),
+	GCLDSTATE(gcregBlock4SrcStrideRegAddrs + 3, 1),
+	GCLDSTATE(gcregBlock8SrcStrideRegAddrs + 4, 1),
+	GCLDSTATE(gcregBlock8SrcStrideRegAddrs + 5, 1),
+	GCLDSTATE(gcregBlock8SrcStrideRegAddrs + 6, 1),
+	GCLDSTATE(gcregBlock8SrcStrideRegAddrs + 7, 1)
+};
+
+static const struct gccmdldstate gcmosrc_rotation_ldst[8] = {
+	GCLDSTATE(gcregSrcRotationConfigRegAddrs, 1),
+	GCLDSTATE(gcregBlock4SrcRotationConfigRegAddrs + 1, 1),
+	GCLDSTATE(gcregBlock4SrcRotationConfigRegAddrs + 2, 1),
+	GCLDSTATE(gcregBlock4SrcRotationConfigRegAddrs + 3, 1),
+	GCLDSTATE(gcregBlock8SrcRotationConfigRegAddrs + 4, 1),
+	GCLDSTATE(gcregBlock8SrcRotationConfigRegAddrs + 5, 1),
+	GCLDSTATE(gcregBlock8SrcRotationConfigRegAddrs + 6, 1),
+	GCLDSTATE(gcregBlock8SrcRotationConfigRegAddrs + 7, 1)
+};
+
+static const struct gccmdldstate gcmosrc_config_ldst[8] = {
+	GCLDSTATE(gcregSrcConfigRegAddrs, 1),
+	GCLDSTATE(gcregBlock4SrcConfigRegAddrs + 1, 1),
+	GCLDSTATE(gcregBlock4SrcConfigRegAddrs + 2, 1),
+	GCLDSTATE(gcregBlock4SrcConfigRegAddrs + 3, 1),
+	GCLDSTATE(gcregBlock8SrcConfigRegAddrs + 4, 1),
+	GCLDSTATE(gcregBlock8SrcConfigRegAddrs + 5, 1),
+	GCLDSTATE(gcregBlock8SrcConfigRegAddrs + 6, 1),
+	GCLDSTATE(gcregBlock8SrcConfigRegAddrs + 7, 1)
+};
+
+static const struct gccmdldstate gcmosrc_origin_ldst[8] = {
+	GCLDSTATE(gcregSrcOriginRegAddrs, 1),
+	GCLDSTATE(gcregBlock4SrcOriginRegAddrs + 1, 1),
+	GCLDSTATE(gcregBlock4SrcOriginRegAddrs + 2, 1),
+	GCLDSTATE(gcregBlock4SrcOriginRegAddrs + 3, 1),
+	GCLDSTATE(gcregBlock8SrcOriginRegAddrs + 4, 1),
+	GCLDSTATE(gcregBlock8SrcOriginRegAddrs + 5, 1),
+	GCLDSTATE(gcregBlock8SrcOriginRegAddrs + 6, 1),
+	GCLDSTATE(gcregBlock8SrcOriginRegAddrs + 7, 1)
+};
+
+static const struct gccmdldstate gcmosrc_size_ldst[8] = {
+	GCLDSTATE(gcregSrcSizeRegAddrs, 1),
+	GCLDSTATE(gcregBlock4SrcSizeRegAddrs + 1, 1),
+	GCLDSTATE(gcregBlock4SrcSizeRegAddrs + 2, 1),
+	GCLDSTATE(gcregBlock4SrcSizeRegAddrs + 3, 1),
+	GCLDSTATE(gcregBlock8SrcSizeRegAddrs + 4, 1),
+	GCLDSTATE(gcregBlock8SrcSizeRegAddrs + 5, 1),
+	GCLDSTATE(gcregBlock8SrcSizeRegAddrs + 6, 1),
+	GCLDSTATE(gcregBlock8SrcSizeRegAddrs + 7, 1)
+};
+
+static const struct gccmdldstate gcmosrc_rotationheight_ldst[8] = {
+	GCLDSTATE(gcregSrcRotationHeightRegAddrs, 1),
+	GCLDSTATE(gcregBlock4SrcRotationHeightRegAddrs + 1, 1),
+	GCLDSTATE(gcregBlock4SrcRotationHeightRegAddrs + 2, 1),
+	GCLDSTATE(gcregBlock4SrcRotationHeightRegAddrs + 3, 1),
+	GCLDSTATE(gcregBlock8SrcRotationHeightRegAddrs + 4, 1),
+	GCLDSTATE(gcregBlock8SrcRotationHeightRegAddrs + 5, 1),
+	GCLDSTATE(gcregBlock8SrcRotationHeightRegAddrs + 6, 1),
+	GCLDSTATE(gcregBlock8SrcRotationHeightRegAddrs + 7, 1)
+};
+
+static const struct gccmdldstate gcmosrc_rotationangle_ldst[8] = {
+	GCLDSTATE(gcregRotAngleRegAddrs, 1),
+	GCLDSTATE(gcregBlock4RotAngleRegAddrs + 1, 1),
+	GCLDSTATE(gcregBlock4RotAngleRegAddrs + 2, 1),
+	GCLDSTATE(gcregBlock4RotAngleRegAddrs + 3, 1),
+	GCLDSTATE(gcregBlock8RotAngleRegAddrs + 4, 1),
+	GCLDSTATE(gcregBlock8RotAngleRegAddrs + 5, 1),
+	GCLDSTATE(gcregBlock8RotAngleRegAddrs + 6, 1),
+	GCLDSTATE(gcregBlock8RotAngleRegAddrs + 7, 1)
+};
+
+static const struct gccmdldstate gcmosrc_rop_ldst[8] = {
+	GCLDSTATE(gcregRopRegAddrs, 1),
+	GCLDSTATE(gcregBlock4RopRegAddrs + 1, 1),
+	GCLDSTATE(gcregBlock4RopRegAddrs + 2, 1),
+	GCLDSTATE(gcregBlock4RopRegAddrs + 3, 1),
+	GCLDSTATE(gcregBlock8RopRegAddrs + 4, 1),
+	GCLDSTATE(gcregBlock8RopRegAddrs + 5, 1),
+	GCLDSTATE(gcregBlock8RopRegAddrs + 6, 1),
+	GCLDSTATE(gcregBlock8RopRegAddrs + 7, 1)
+};
+
+static const struct gccmdldstate gcmosrc_mult_ldst[8] = {
+	GCLDSTATE(gcregColorMultiplyModesRegAddrs, 1),
+	GCLDSTATE(gcregBlock4ColorMultiplyModesRegAddrs + 1, 1),
+	GCLDSTATE(gcregBlock4ColorMultiplyModesRegAddrs + 2, 1),
+	GCLDSTATE(gcregBlock4ColorMultiplyModesRegAddrs + 3, 1),
+	GCLDSTATE(gcregBlock8ColorMultiplyModesRegAddrs + 4, 1),
+	GCLDSTATE(gcregBlock8ColorMultiplyModesRegAddrs + 5, 1),
+	GCLDSTATE(gcregBlock8ColorMultiplyModesRegAddrs + 6, 1),
+	GCLDSTATE(gcregBlock8ColorMultiplyModesRegAddrs + 7, 1)
+};
+
+struct gcmosrc {
+	/* gcregBlock4SrcAddressRegAddrs */
+	struct gccmdldstate address_ldst;
+
+		/* gcregBlock4SrcAddressRegAddrs */
+		unsigned int address;
+
+	/* gcregBlock4SrcStrideRegAddrs */
+	struct gccmdldstate stride_ldst;
+
+		/* gcregBlock4SrcStrideRegAddrs */
+		unsigned int stride;
+
+	/* gcregBlock4SrcRotationConfigRegAddrs */
+	struct gccmdldstate rotation_ldst;
+
+		/* gcregBlock4SrcRotationConfigRegAddrs */
+		union {
+			struct gcregsrcrotationconfig reg;
+			unsigned int raw;
+		} rotation;
+
+	/* gcregBlock4SrcConfigRegAddrs */
+	struct gccmdldstate config_ldst;
+
+		/* gcregBlock4SrcConfigRegAddrs */
+		union {
+			struct gcregsrcconfig reg;
+			unsigned int raw;
+		} config;
+
+	/* gcregBlock4SrcOriginRegAddrs */
+	struct gccmdldstate origin_ldst;
+
+		/* gcregBlock4SrcOriginRegAddrs */
+		union {
+			struct gcregsrcorigin reg;
+			unsigned int raw;
+		} origin;
+
+	/* gcregBlock4SrcSizeRegAddrs */
+	struct gccmdldstate size_ldst;
+
+		/* gcregBlock4SrcSizeRegAddrs */
+		union {
+			struct gcregsrcsize reg;
+			unsigned int raw;
+		} size;
+
+	/* gcregBlock4SrcRotationHeightRegAddrs */
+	struct gccmdldstate rotationheight_ldst;
+
+		/* gcregBlock4SrcRotationHeightRegAddrs */
+		union {
+			struct gcregsrcrotationheight reg;
+			unsigned int raw;
+		} rotationheight;
+
+	/* gcregBlock4RotAngleRegAddrs */
+	struct gccmdldstate rotationangle_ldst;
+
+		/* gcregBlock4RotAngleRegAddrs */
+		union {
+			struct gcregrotangle reg;
+			unsigned int raw;
+		} rotationangle;
+
+	/* gcregBlock4RopRegAddrs */
+	struct gccmdldstate rop_ldst;
+
+		/* gcregBlock4RopRegAddrs */
+		union {
+			struct gcregrop reg;
+			unsigned int raw;
+		} rop;
+
+	/* gcregBlock4ColorMultiplyModesRegAddrs */
+	struct gccmdldstate mult_ldst;
+
+		/* gcregBlock4ColorMultiplyModesRegAddrs */
+		union {
+			struct gcregcolormultiplymodes reg;
+			unsigned int raw;
+		} mult;
+};
+
+static const struct gccmdldstate gcmovrsrc_config_ldst =
+	GCLDSTATE(gcregSrcAddressRegAddrs, 4);
+
+static const struct gccmdldstate gcmovrsrc_pos_ldst =
+	GCLDSTATE(gcregVRSourceImageLowRegAddrs, 4);
+
+static const struct gccmdldstate gcmovrsrc_rotation_ldst =
+	GCLDSTATE(gcregSrcRotationHeightRegAddrs, 2);
+
+static const struct gccmdldstate gcmovrsrc_rop_ldst =
+	GCLDSTATE(gcregRopRegAddrs, 1);
+
+static const struct gccmdldstate gcmovrsrc_mult_ldst =
+	GCLDSTATE(gcregColorMultiplyModesRegAddrs, 1);
+
+struct gcmovrsrc {
+	/* Configuration block. */
+	struct gccmdldstate config_ldst;
+
+		/* gcregSrcAddressRegAddrs */
+		unsigned int address;
+
+		/* gcregSrcStrideRegAddrs */
+		unsigned int stride;
+
+		/* gcregSrcRotationConfigRegAddrs */
+		union {
+			struct gcregsrcrotationconfig reg;
+			unsigned int raw;
+		} rotation;
+
+		/* gcregSrcConfigRegAddrs */
+		union {
+			struct gcregsrcconfig reg;
+			unsigned int raw;
+		} config;
+
+		/* Alignment filler. */
+		unsigned int _filler1;
+
+	/* Source position block. */
+	struct gccmdldstate pos_ldst;
+
+		/* gcregVRSourceImageLowRegAddrs */
+		union {
+			struct gcregvrsourceimagelow reg;
+			unsigned int raw;
+		} lt;
+
+		/* gcregVRSourceImageHighRegAddrs */
+		union {
+			struct gcregvrsourceimagehigh reg;
+			unsigned int raw;
+		} rb;
+
+		/* gcregVRSourceOriginLowRegAddrs */
+		unsigned int x;
+
+		/* gcregVRSourceOriginHighRegAddrs */
+		unsigned int y;
+
+		/* Alignment filler. */
+		unsigned int _filler2;
+
+	/* Rotation block. */
+	struct gccmdldstate rotation_ldst;
+
+		/* gcregSrcRotationHeightRegAddrs */
+		union {
+			struct gcregsrcrotationheight reg;
+			unsigned int raw;
+		} rotationheight;
+
+		/* gcregRotAngleRegAddrs */
+		union {
+			struct gcregrotangle reg;
+			unsigned int raw;
+		} rotationangle;
+
+		/* Alignment filler. */
+		unsigned int _filler3;
+
+	/* gcregRopRegAddrs */
+	struct gccmdldstate rop_ldst;
+
+		/* gcregRopRegAddrs */
+		union {
+			struct gcregrop reg;
+			unsigned int raw;
+		} rop;
+
+	/* gcregColorMultiplyModesRegAddrs */
+	struct gccmdldstate mult_ldst;
+
+		/* gcregColorMultiplyModesRegAddrs */
+		union {
+			struct gcregcolormultiplymodes reg;
+			unsigned int raw;
+		} mult;
+};
+
+/*******************************************************************************
+** Modular operations: bltconfig
+*/
+
+static const struct gccmdldstate gcmobltconfig_multisource_ldst =
+	GCLDSTATE(gcregDEMultiSourceRegAddrs, 1);
+
+static const struct gccmdldstate gcmobltconfig_dstconfig_ldst =
+	GCLDSTATE(gcregDestConfigRegAddrs, 1);
+
+struct gcmobltconfig {
+	/* gcregDEMultiSourceRegAddrs */
+	struct gccmdldstate multisource_ldst;
+
+		/* gcregDEMultiSourceRegAddrs */
+		union {
+			struct gcregmultisource reg;
+			unsigned int raw;
+		} multisource;
+
+	/* gcregDestConfigRegAddrs */
+	struct gccmdldstate dstconfig_ldst;
+
+		/* gcregDestConfigRegAddrs */
+		union {
+			struct gcregdstconfig reg;
+			unsigned int raw;
+		} dstconfig;
+};
+
+/*******************************************************************************
+** Modular operations: startde
+*/
+
+struct gcmostartde {
+	/* Start DE command. */
+	struct gccmdstartde startde;
+	struct gccmdstartderect rect;
+};
+
+/*******************************************************************************
+** Modular operations: fillsrc
+*/
+
+static const struct gccmdldstate gcmofillsrc_rotation_ldst =
+	GCLDSTATE(gcregSrcRotationConfigRegAddrs, 2);
+
+static const struct gccmdldstate gcmofillsrc_rotationheight_ldst =
+	GCLDSTATE(gcregSrcRotationHeightRegAddrs, 2);
+
+static const struct gccmdldstate gcmofillsrc_alphacontrol_ldst =
+	GCLDSTATE(gcregAlphaControlRegAddrs, 1);
+
+struct gcmofillsrc {
+	/* gcregSrcRotationConfigRegAddrs */
+	struct gccmdldstate rotation_ldst;
+
+		/* gcregSrcRotationConfigRegAddrs */
+		union {
+			struct gcregsrcrotationconfig reg;
+			unsigned int raw;
+		} rotation;
+
+		/* gcregSrcConfigRegAddrs */
+		union {
+			struct gcregsrcconfig reg;
+			unsigned int raw;
+		} config;
+
+		/* Alignment filler. */
+		unsigned int _filler1;
+
+	/* gcregSrcRotationHeightRegAddrs */
+	struct gccmdldstate rotationheight_ldst;
+
+		/* gcregSrcRotationHeightRegAddrs */
+		union {
+			struct gcregsrcrotationheight reg;
+			unsigned int raw;
+		} rotationheight;
+
+		/* gcregRotAngleRegAddrs */
+		union {
+			struct gcregrotangle reg;
+			unsigned int raw;
+		} rotationangle;
+
+		/* Alignment filler. */
+		unsigned int _filler2;
+
+	/* gcregAlphaControlRegAddrs */
+	struct gccmdldstate alphacontrol_ldst;
+
+		/* gcregAlphaControlRegAddrs */
+		union {
+			struct gcregalphacontrol reg;
+			unsigned int raw;
+		} alphacontrol;
+};
+
+/*******************************************************************************
+** Modular operations: fill
+*/
+
+static const struct gccmdldstate gcmofill_clearcolor_ldst =
+	GCLDSTATE(gcregClearPixelValue32RegAddrs, 1);
+
+static const struct gccmdldstate gcmofill_dstconfig_ldst =
+	GCLDSTATE(gcregDestConfigRegAddrs, 1);
+
+static const struct gccmdldstate gcmofill_rop_ldst =
+	GCLDSTATE(gcregRopRegAddrs, 1);
+
+struct gcmofill {
+	struct gcmofillsrc src;
+
+	/* gcregClearPixelValue32RegAddrs */
+	struct gccmdldstate clearcolor_ldst;
+
+		/* gcregClearPixelValue32RegAddrs */
+		union {
+			struct gcregclearcolor reg;
+			unsigned int raw;
+		} clearcolor;
+
+	/* gcregDestConfigRegAddrs */
+	struct gccmdldstate dstconfig_ldst;
+
+		/* gcregDestConfigRegAddrs */
+		union {
+			struct gcregdstconfig reg;
+			unsigned int raw;
+		} dstconfig;
+
+	/* gcregRopRegAddrs */
+	struct gccmdldstate rop_ldst;
+
+		/* gcregRopRegAddrs */
+		union {
+			struct gcregrop reg;
+			unsigned int raw;
+		} rop;
+
+	/* Start DE command. */
+	struct gccmdstartde startde;
+	struct gccmdstartderect rect;
+};
+
+/*******************************************************************************
+** Modular operations: filterkernel
+*/
+
+static const struct gccmdldstate gcmofilterkernel_shared_ldst =
+	GCLDSTATE(gcregFilterKernelRegAddrs, 77);
+
+static const struct gccmdldstate gcmofilterkernel_horizontal_ldst =
+	GCLDSTATE(gcregHoriFilterKernelRegAddrs, 77);
+
+static const struct gccmdldstate gcmofilterkernel_vertical_ldst =
+	GCLDSTATE(gcregVertiFilterKernelRegAddrs, 77);
+
+struct gcmofilterkernel {
+	/* Kernel array block. */
+	struct gccmdldstate kernelarray_ldst;
+
+		/* Array of kernel coefficients. */
+		struct gcregfilterkernel kernelarray;
+};
+
+/*******************************************************************************
+** Modular operations: vrdst
+*/
+
+static const struct gccmdldstate gcmovrdst_config_ldst =
+	GCLDSTATE(gcregDestAddressRegAddrs, 4);
+
+static const struct gccmdldstate gcmovrdst_rotationheight_ldst =
+	GCLDSTATE(gcregDstRotationHeightRegAddrs, 1);
+
+struct gcmovrdst {
+	/* Configuration block. */
+	struct gccmdldstate config_ldst;
+
+		/* gcregDestAddressRegAddrs */
+		unsigned int address;
+
+		/* gcregDestStrideRegAddrs */
+		unsigned int stride;
+
+		/* gcregDestRotationConfigRegAddrs */
+		union {
+			struct gcregdstrotationconfig reg;
+			unsigned int raw;
+		} rotation;
+
+		/* gcregDestConfigRegAddrs */
+		union {
+			struct gcregdstconfig reg;
+			unsigned int raw;
+		} config;
+
+		/* Alignment filler. */
+		unsigned int _filler;
+
+	/* gcregDstRotationHeightRegAddrs */
+	struct gccmdldstate rotationheight_ldst;
+
+		/* gcregDstRotationHeightRegAddrs */
+		union {
+			struct gcregdstrotationheight reg;
+			unsigned int raw;
+		} rotationheight;
+};
+
+/*******************************************************************************
+** Modular operations: vrconfigex
+*/
+
+static const struct gccmdldstate gcmovrconfigex_config_ldst =
+	GCLDSTATE(gcregVRConfigExRegAddrs, 1);
+
+struct gcmovrconfigex {
+	/* gcregVRConfigExRegAddrs */
+	struct gccmdldstate config_ldst;
+
+		/* gcregVRConfigExRegAddrs */
+		union {
+			struct gcregvrconfigex reg;
+			unsigned int raw;
+		} config;
+};
+
+/*******************************************************************************
+** Modular operations: startvr
+*/
+
+static const struct gccmdldstate gcmostartvr_scale_ldst =
+	GCLDSTATE(gcregStretchFactorLowRegAddrs, 2);
+
+static const struct gccmdldstate gcmostartvr_rect_ldst =
+	GCLDSTATE(gcregVRTargetWindowLowRegAddrs, 2);
+
+static const struct gccmdldstate gcmostartvr_config_ldst =
+	GCLDSTATE(gcregVRConfigRegAddrs, 1);
+
+struct gcmostartvr {
+	/* Scale factor block. */
+	struct gccmdldstate scale_ldst;
+
+		/* gcregStretchFactorLowRegAddrs */
+		unsigned int scalex;
+
+		/* gcregStretchFactorHighRegAddrs */
+		unsigned int scaley;
+
+		/* Alignment filler. */
+		unsigned int _filler1;
+
+	/* Target rectangle. */
+	struct gccmdldstate rect_ldst;
+
+		/* gcregVRTargetWindowLowRegAddrs */
+		struct gcregvrtargetwindowlow lt;
+
+		/* gcregVRTargetWindowHighRegAddrs */
+		struct gcregvrtargetwindowhigh rb;
+
+		/* Alignment filler. */
+		unsigned int _filler2;
+
+	/* Start video raster commad. */
+	struct gccmdldstate config_ldst;
+
+		/* gcregVRConfigRegAddrs */
+		struct gcregvrconfig config;
+};
+
+#endif
diff --git a/include/linux/gcx.h b/include/linux/gcx.h
new file mode 100644
index 0000000..0d3994a
--- /dev/null
+++ b/include/linux/gcx.h
@@ -0,0 +1,106 @@
+/*
+ * gcx.h
+ *
+ * Copyright (C) 2010-2011 Vivante Corporation.
+ *
+ * This package is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#ifndef GCX_H
+#define GCX_H
+
+#include "semaphore.h"
+#include "gcerror.h"
+#include "gcreg.h"
+#include "gcdbglog.h"
+#include "gcdebug.h"
+
+#ifndef countof
+#define countof(a) \
+( \
+	sizeof(a) / sizeof(a[0]) \
+)
+#endif
+
+#define GC_PTR2INT(p) \
+( \
+	(unsigned int) (p) \
+)
+
+#define GC_ALIGN(n, align) \
+( \
+	((n) + ((align) - 1)) & ~((align) - 1) \
+)
+
+#define GCLOCK_TIMEOUT_SEC 10
+#define GCLOCK_TIMEOUT_JIF (msecs_to_jiffies(GCLOCK_TIMEOUT_SEC * 1000))
+
+#define GCLOCK_TYPE \
+	struct semaphore
+
+#define GCDEFINE_LOCK(name) \
+	DEFINE_SEMAPHORE(name)
+
+#define GCLOCK_INIT(lock) \
+	sema_init(lock, 1)
+
+#define GCLOCK_DESTROY(lock) \
+	do { } while (0)
+
+#define GCLOCK(lock) { \
+	unsigned long __result__; \
+	while (true) { \
+		__result__ = down_timeout(lock, GCLOCK_TIMEOUT_JIF); \
+		if (__result__ == 0) \
+			break; \
+		printk(KERN_ERR "%s(%d) GCLOCK timeout (%lu).\n", \
+		       __func__, __LINE__, __result__); \
+		GCGPUSTATUS();					  \
+		printk(KERN_INFO "%s(%d)\n", __func__, __LINE__); \
+	} \
+}
+
+#define GCUNLOCK(lock) \
+	up(lock)
+
+#define GCWAIT_FOR_COMPLETION(completion) { \
+	unsigned long __result__; \
+	while (true) { \
+		__result__ = wait_for_completion_timeout(completion, \
+							GCLOCK_TIMEOUT_JIF); \
+		if (__result__ != 0) \
+			break; \
+		printk(KERN_ERR \
+		       "%s(%d) GCWAIT_FOR_COMPLETION timeout (%lu).\n", \
+		       __func__, __LINE__, __result__); \
+		GCGPUSTATUS();					  \
+		printk(KERN_INFO "%s(%d)\n", __func__, __LINE__); \
+	} \
+}
+
+#define GCWAIT_FOR_COMPLETION_TIMEOUT(result, completion, timeout) { \
+	if (timeout == MAX_SCHEDULE_TIMEOUT) { \
+		while (true) { \
+			result = wait_for_completion_timeout(completion, \
+							GCLOCK_TIMEOUT_JIF); \
+			if (result != 0) \
+				break; \
+			printk(KERN_ERR \
+			       "%s(%d) GCWAIT_FOR_COMPLETION_TIMEOUT" \
+			       " timeout (%lu).\n", \
+			       __func__, __LINE__, result); \
+			GCGPUSTATUS();					\
+			printk(KERN_INFO "%s(%d)\n", __func__, __LINE__); \
+		} \
+	} else { \
+		result = wait_for_completion_timeout(completion, timeout); \
+	} \
+}
+
+#endif
-- 
1.7.1

