# 
# old_revision [95220d9f8a309c487f6d8da20ce7f8df8945bc0c]
# 
# add_file "packages/linux/linux-openmoko/glamo-report-vram-size-to-userspace.patch"
#  content [c9d35297bee6c1f0e66123fe4919e96dc632cf70]
# 
# add_file "packages/xorg-xserver/xserver-kdrive-1.3.0.0/build-glamo.patch"
#  content [cc0e9b8762c22daff42051281744706d62d5803b]
# 
# add_file "packages/xorg-xserver/xserver-kdrive-1.3.0.0/smedia-glamo.patch"
#  content [9e6bb0c7c7556483765850cbd03efcd3fd9a55d8]
# 
# patch "packages/linux/linux-openmoko_2.6.22.5.bb"
#  from [7e0cfda05ce43d08a2e2830dc6d3cbe28cf52bd6]
#    to [2403ba846329f9d07c4852a702f505eebde7351f]
# 
# patch "packages/xorg-xserver/xserver-kdrive-common.inc"
#  from [41111959110e4d02e8cbcb965b17cd1d2494d5b9]
#    to [243bcb1cf8f6d81256ea0e31b07b0478b9bb5174]
# 
# patch "packages/xorg-xserver/xserver-kdrive_1.3.0.0.bb"
#  from [bc48ac913bf5619e2ef613e1dcc2f78c81bcd221]
#    to [de61c2062ad218eabe75d458171196d03d0f9181]
# 
============================================================
--- packages/linux/linux-openmoko/glamo-report-vram-size-to-userspace.patch	c9d35297bee6c1f0e66123fe4919e96dc632cf70
+++ packages/linux/linux-openmoko/glamo-report-vram-size-to-userspace.patch	c9d35297bee6c1f0e66123fe4919e96dc632cf70
@@ -0,0 +1,67 @@
+From ff1564e5100eeccd53ee6b007813ea722f8cf8b6 Mon Sep 17 00:00:00 2001
+From: Chia-I Wu <olv@openmoko.com>
+Date: Mon, 1 Oct 2007 21:16:46 +0800
+Subject: [PATCH] glamo: report vram size to userspace
+
+Set fb_fix_screeninfo.smem_len to RESSIZE(fb_res).  This is not the real
+vram size, as it is a hardcoded value in glamo-core.c for now.
+---
+ drivers/video/glamo/glamo-fb.c |   13 +++++--------
+ 1 files changed, 5 insertions(+), 8 deletions(-)
+
+diff --git a/drivers/video/glamo/glamo-fb.c b/drivers/video/glamo/glamo-fb.c
+index 451de75..160a5b1 100644
+--- a/drivers/video/glamo/glamo-fb.c
++++ b/drivers/video/glamo/glamo-fb.c
+@@ -54,8 +54,6 @@
+ 
+ #define RESSIZE(ressource) (((ressource)->end - (ressource)->start)+1)
+ 
+-#define GLAMO_FB_ALLOC	(640*480*2)
+-
+ struct glamofb_handle {
+ 	struct fb_info *fb;
+ 	struct device *dev;
+@@ -224,7 +222,6 @@ static int glamofb_set_par(struct fb_info *info)
+ 	}
+ 
+ 	glamo->fb->fix.line_length = (var->width * var->bits_per_pixel) / 8;
+-	glamo->fb->fix.smem_len = info->fix.line_length * var->yres_virtual;
+ 
+ 	return 0;
+ }
+@@ -453,7 +450,7 @@ static int __init glamofb_probe(struct platform_device *pdev)
+ 	}
+ 
+ 	glamofb->fb_res = request_mem_region(glamofb->fb_res->start,
+-					     GLAMO_FB_ALLOC, pdev->name);
++					     RESSIZE(glamofb->fb_res), pdev->name);
+ 	if (!glamofb->fb_res) {
+ 		dev_err(&pdev->dev, "failed to request vram region\n");
+ 		goto out_release_reg;
+@@ -467,6 +464,7 @@ static int __init glamofb_probe(struct platform_device *pdev)
+ 		goto out_release_fb;
+ 	}
+ 	fbinfo->fix.smem_start = (unsigned long) glamofb->fb_res->start;
++	fbinfo->fix.smem_len = RESSIZE(glamofb->fb_res);
+ 
+ 	fbinfo->screen_base = ioremap(glamofb->fb_res->start,
+ 				       RESSIZE(glamofb->fb_res));
+@@ -522,11 +520,10 @@ static int __init glamofb_probe(struct platform_device *pdev)
+ 	fbinfo->var.green.length = 6;
+ 	fbinfo->var.blue.length = 5;
+ 	fbinfo->var.transp.length = 0;
+-	fbinfo->fix.smem_len = mach_info->xres.max *
+-			       mach_info->yres.max *
+-			       mach_info->bpp.max / 8;
+ 
+-	memset(fbinfo->screen_base, 0, fbinfo->fix.smem_len);
++	memset(fbinfo->screen_base, 0, mach_info->xres.max *
++				       mach_info->yres.max *
++				       mach_info->bpp.max / 8);
+ 
+ 	glamo_engine_enable(mach_info->glamo, GLAMO_ENGINE_LCD);
+ 	glamo_engine_reset(mach_info->glamo, GLAMO_ENGINE_LCD);
+-- 
+1.5.3.1
+
============================================================
--- packages/xorg-xserver/xserver-kdrive-1.3.0.0/build-glamo.patch	cc0e9b8762c22daff42051281744706d62d5803b
+++ packages/xorg-xserver/xserver-kdrive-1.3.0.0/build-glamo.patch	cc0e9b8762c22daff42051281744706d62d5803b
@@ -0,0 +1,76 @@
+diff --git a/configure.ac b/configure.ac
+index 76d33f0..2807c50 100644
+--- a/configure.ac
++++ b/configure.ac
+@@ -1824,6 +1824,7 @@ hw/kdrive/ati/Makefile
+ hw/kdrive/chips/Makefile
+ hw/kdrive/ephyr/Makefile
+ hw/kdrive/epson/Makefile
++hw/kdrive/glamo/Makefile
+ hw/kdrive/fake/Makefile
+ hw/kdrive/fbdev/Makefile
+ hw/kdrive/w100/Makefile
+diff --git a/hw/kdrive/Makefile.am b/hw/kdrive/Makefile.am
+index 8075a56..b97912d 100644
+--- a/hw/kdrive/Makefile.am
++++ b/hw/kdrive/Makefile.am
+@@ -4,7 +4,7 @@ VESA_SUBDIRS = vesa ati chips epson i810 mach64 mga neomagic nvidia pm2 r128 \
+ endif
+ 
+ if KDRIVEFBDEV
+-FBDEV_SUBDIRS = fbdev epson
++FBDEV_SUBDIRS = fbdev epson glamo
+ endif
+ 
+ if KDRIVEW100
+@@ -34,4 +34,4 @@ SUBDIRS =			\
+ 	fake
+ 
+ DIST_SUBDIRS = vesa ati chips epson i810 mach64 mga neomagic nvidia pm2 r128 \
+-               smi via fbdev sdl ephyr src linux fake sis300
++               smi via fbdev sdl ephyr src linux fake sis300 glamo
+diff --git a/hw/kdrive/glamo/Makefile.am b/hw/kdrive/glamo/Makefile.am
+index e8c48a4..ffb7a30 100644
+--- a/hw/kdrive/glamo/Makefile.am
++++ b/hw/kdrive/glamo/Makefile.am
+@@ -41,11 +41,14 @@ GLAMO_LIBS =				\
+ 
+ Xglamo_LDADD = \
+ 	$(GLAMO_LIBS)			\
+-	@KDRIVE_LIBS@
++	@KDRIVE_LIBS@			\
++	@XSERVER_LIBS@
+ 
+ Xglamo_DEPENDENCIES =	\
+ 	libglamo.a 			\
+-	@KDRIVE_LOCAL_LIBS@
++        $(FBDEV_LIBS)                   \
++        $(VESA_LIBS)                    \
++        $(DRI_LIBS)
+ 
+ relink:
+ 	rm -f $(bin_PROGRAMS) && make $(bin_PROGRAMS)
+diff --git a/hw/kdrive/glamo/glamo_stub.c b/hw/kdrive/glamo/glamo_stub.c
+index d772671..df43455 100644
+--- a/hw/kdrive/glamo/glamo_stub.c
++++ b/hw/kdrive/glamo/glamo_stub.c
+@@ -49,16 +49,10 @@ InitOutput(ScreenInfo *pScreenInfo, int argc, char **argv)
+ void
+ InitInput(int argc, char **argv)
+ {
+-	KdKeyboardInfo *ki;
+-
+-	KdAddKeyboardDriver(&LinuxKeyboardDriver);
+-	KdAddPointerDriver(&LinuxMouseDriver);
+-#ifdef TSLIB
+-	KdAddPointerDriver(&TsDriver);
++	KdInitInput (&LinuxEvdevMouseFuncs, &LinuxEvdevKeyboardFuncs);
++#ifdef TOUCHSCREEN
++	KdAddMouseDriver (&TsFuncs);
+ #endif
+-
+-	ki = KdParseKeyboard("keybd");
+-	KdAddKeyboard(ki);
+ }
+ 
+ void
============================================================
--- packages/xorg-xserver/xserver-kdrive-1.3.0.0/smedia-glamo.patch	9e6bb0c7c7556483765850cbd03efcd3fd9a55d8
+++ packages/xorg-xserver/xserver-kdrive-1.3.0.0/smedia-glamo.patch	9e6bb0c7c7556483765850cbd03efcd3fd9a55d8
@@ -0,0 +1,3702 @@
+Index: xserver/hw/kdrive/glamo/Makefile.am
+===================================================================
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ xserver/hw/kdrive/glamo/Makefile.am	2007-09-25 19:32:10.000000000 +0800
+@@ -0,0 +1,51 @@
++if KDRIVEFBDEV
++FBDEV_INCLUDES =-I$(top_srcdir)/hw/kdrive/fbdev
++FBDEV_LIBS = $(top_builddir)/hw/kdrive/fbdev/libfbdev.a
++endif
++
++if KDRIVEVESA
++VESA_INCLUDES = -I$(top_srcdir)/hw/kdrive/vesa
++VESA_LIBS = $(top_builddir)/hw/kdrive/vesa/libvesa.a
++endif
++
++INCLUDES = 					\
++	@KDRIVE_INCS@				\
++	$(DRI_INCLUDES)				\
++	$(FBDEV_INCLUDES)			\
++	$(VESA_INCLUDES)			\
++	@KDRIVE_CFLAGS@
++
++bin_PROGRAMS = Xglamo
++
++noinst_LIBRARIES = libglamo.a
++
++libglamo_a_SOURCES = 	\
++	glamo_dma.c	\
++	glamo_dma.h	\
++	glamo_draw.c	\
++	glamo_draw.h	\
++	glamo.c		\
++	glamo.h		\
++	glamo-regs.h	\
++	glamo_video.c
++
++Xglamo_SOURCES = \
++	glamo_stub.c
++
++GLAMO_LIBS =				\
++	libglamo.a 			\
++	$(FBDEV_LIBS)			\
++	$(VESA_LIBS)			\
++	$(DRI_LIBS)			\
++	@KDRIVE_LIBS@
++
++Xglamo_LDADD = \
++	$(GLAMO_LIBS)			\
++	@KDRIVE_LIBS@
++
++Xglamo_DEPENDENCIES =	\
++	libglamo.a 			\
++	@KDRIVE_LOCAL_LIBS@
++
++relink:
++	rm -f $(bin_PROGRAMS) && make $(bin_PROGRAMS)
+Index: xserver/hw/kdrive/glamo/glamo-regs.h
+===================================================================
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ xserver/hw/kdrive/glamo/glamo-regs.h	2007-09-25 19:00:20.000000000 +0800
+@@ -0,0 +1,685 @@
++#ifndef _GLAMO_REGS_H
++#define _GLAMO_REGS_H
++
++/* Smedia Glamo 336x/337x driver
++ *
++ * (C) 2007 by OpenMoko, Inc.
++ * Author: Harald Welte <laforge@openmoko.org>
++ * All rights reserved.
++ *
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License as
++ * published by the Free Software Foundation; either version 2 of
++ * the License, or (at your option) any later version.
++ *
++ * 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., 59 Temple Place, Suite 330, Boston,
++ * MA 02111-1307 USA
++ */
++
++enum glamo_regster_offsets {
++	GLAMO_REGOFS_GENERIC	= 0x0000,
++	GLAMO_REGOFS_HOSTBUS	= 0x0200,
++	GLAMO_REGOFS_MEMORY	= 0x0300,
++	GLAMO_REGOFS_VIDCAP	= 0x0400,
++	GLAMO_REGOFS_ISP	= 0x0500,
++	GLAMO_REGOFS_JPEG	= 0x0800,
++	GLAMO_REGOFS_MPEG	= 0x0c00,
++	GLAMO_REGOFS_LCD	= 0x1100,
++	GLAMO_REGOFS_MMC	= 0x1400,
++	GLAMO_REGOFS_MPROC0	= 0x1500,
++	GLAMO_REGOFS_MPROC1	= 0x1580,
++	GLAMO_REGOFS_CMDQUEUE	= 0x1600,
++	GLAMO_REGOFS_RISC	= 0x1680,
++	GLAMO_REGOFS_2D		= 0x1700,
++	GLAMO_REGOFS_3D		= 0x1b00,
++};
++
++
++enum glamo_register_generic {
++	GLAMO_REG_GCONF1	= 0x0000,
++	GLAMO_REG_GCONF2	= 0x0002,
++#define	GLAMO_REG_DEVICE_ID	GLAMO_REG_GCONF2
++	GLAMO_REG_GCONF3	= 0x0004,
++#define	GLAMO_REG_REVISION_ID	GLAMO_REG_GCONF3
++	GLAMO_REG_IRQ_GEN1	= 0x0006,
++#define GLAMO_REG_IRQ_ENABLE	GLAMO_REG_IRQ_GEN1
++	GLAMO_REG_IRQ_GEN2	= 0x0008,
++#define GLAMO_REG_IRQ_SET	GLAMO_REG_IRQ_GEN2
++	GLAMO_REG_IRQ_GEN3	= 0x000a,
++#define GLAMO_REG_IRQ_CLEAR	GLAMO_REG_IRQ_GEN3
++	GLAMO_REG_IRQ_GEN4	= 0x000c,
++#define GLAMO_REG_IRQ_STATUS	GLAMO_REG_IRQ_GEN4
++	GLAMO_REG_CLOCK_HOST	= 0x0010,
++	GLAMO_REG_CLOCK_MEMORY	= 0x0012,
++	GLAMO_REG_CLOCK_LCD	= 0x0014,
++	GLAMO_REG_CLOCK_MMC	= 0x0016,
++	GLAMO_REG_CLOCK_ISP	= 0x0018,
++	GLAMO_REG_CLOCK_JPEG	= 0x001a,
++	GLAMO_REG_CLOCK_3D	= 0x001c,
++	GLAMO_REG_CLOCK_2D	= 0x001e,
++	GLAMO_REG_CLOCK_RISC1	= 0x0020,	/* 3365 only? */
++	GLAMO_REG_CLOCK_RISC2	= 0x0022,	/* 3365 only? */
++	GLAMO_REG_CLOCK_MPEG	= 0x0024,
++	GLAMO_REG_CLOCK_MPROC	= 0x0026,
++
++	GLAMO_REG_CLOCK_GEN5_1	= 0x0030,
++	GLAMO_REG_CLOCK_GEN5_2	= 0x0032,
++	GLAMO_REG_CLOCK_GEN6	= 0x0034,
++	GLAMO_REG_CLOCK_GEN7	= 0x0036,
++	GLAMO_REG_CLOCK_GEN8	= 0x0038,
++	GLAMO_REG_CLOCK_GEN9	= 0x003a,
++	GLAMO_REG_CLOCK_GEN10	= 0x003c,
++	GLAMO_REG_CLOCK_GEN11	= 0x003e,
++	GLAMO_REG_PLL_GEN1	= 0x0040,
++	GLAMO_REG_PLL_GEN2	= 0x0042,
++	GLAMO_REG_PLL_GEN3	= 0x0044,
++	GLAMO_REG_PLL_GEN4	= 0x0046,
++	GLAMO_REG_PLL_GEN5	= 0x0048,
++	GLAMO_REG_GPIO_GEN1	= 0x0050,
++	GLAMO_REG_GPIO_GEN2	= 0x0052,
++	GLAMO_REG_GPIO_GEN3	= 0x0054,
++	GLAMO_REG_GPIO_GEN4	= 0x0056,
++	GLAMO_REG_GPIO_GEN5	= 0x0058,
++	GLAMO_REG_GPIO_GEN6	= 0x005a,
++	GLAMO_REG_GPIO_GEN7	= 0x005c,
++	GLAMO_REG_GPIO_GEN8	= 0x005e,
++	GLAMO_REG_GPIO_GEN9	= 0x0060,
++	GLAMO_REG_GPIO_GEN10	= 0x0062,
++	GLAMO_REG_DFT_GEN1	= 0x0070,
++	GLAMO_REG_DFT_GEN2	= 0x0072,
++	GLAMO_REG_DFT_GEN3	= 0x0074,
++	GLAMO_REG_DFT_GEN4	= 0x0076,
++
++	GLAMO_REG_DFT_GEN5	= 0x01e0,
++	GLAMO_REG_DFT_GEN6	= 0x01f0,
++};
++
++#define GLAMO_REG_HOSTBUS(x)	(GLAMO_REGOFS_HOSTBUS-2+(x*2))
++
++#define REG_MEM(x)		(GLAMO_REGOFS_MEMORY+(x))
++#define GLAMO_REG_MEM_TIMING(x)	(GLAMO_REG_MEM_TIMING1-2+(x*2))
++
++enum glamo_register_mem {
++	GLAMO_REG_MEM_TYPE	= REG_MEM(0x00),
++	GLAMO_REG_MEM_GEN	= REG_MEM(0x02),
++	GLAMO_REG_MEM_TIMING1	= REG_MEM(0x04),
++	GLAMO_REG_MEM_TIMING2	= REG_MEM(0x06),
++	GLAMO_REG_MEM_TIMING3	= REG_MEM(0x08),
++	GLAMO_REG_MEM_TIMING4	= REG_MEM(0x0a),
++	GLAMO_REG_MEM_TIMING5	= REG_MEM(0x0c),
++	GLAMO_REG_MEM_TIMING6	= REG_MEM(0x0e),
++	GLAMO_REG_MEM_TIMING7	= REG_MEM(0x10),
++	GLAMO_REG_MEM_TIMING8	= REG_MEM(0x12),
++	GLAMO_REG_MEM_TIMING9	= REG_MEM(0x14),
++	GLAMO_REG_MEM_TIMING10	= REG_MEM(0x16),
++	GLAMO_REG_MEM_TIMING11	= REG_MEM(0x18),
++	GLAMO_REG_MEM_POWER1	= REG_MEM(0x1a),
++	GLAMO_REG_MEM_POWER2	= REG_MEM(0x1c),
++	GLAMO_REG_MEM_LCD_BUF1	= REG_MEM(0x1e),
++	GLAMO_REG_MEM_LCD_BUF2	= REG_MEM(0x20),
++	GLAMO_REG_MEM_LCD_BUF3	= REG_MEM(0x22),
++	GLAMO_REG_MEM_LCD_BUF4	= REG_MEM(0x24),
++	GLAMO_REG_MEM_BIST1	= REG_MEM(0x26),
++	GLAMO_REG_MEM_BIST2	= REG_MEM(0x28),
++	GLAMO_REG_MEM_BIST3	= REG_MEM(0x2a),
++	GLAMO_REG_MEM_BIST4	= REG_MEM(0x2c),
++	GLAMO_REG_MEM_BIST5	= REG_MEM(0x2e),
++	GLAMO_REG_MEM_MAH1	= REG_MEM(0x30),
++	GLAMO_REG_MEM_MAH2	= REG_MEM(0x32),
++	GLAMO_REG_MEM_DRAM1	= REG_MEM(0x34),
++	GLAMO_REG_MEM_DRAM2	= REG_MEM(0x36),
++	GLAMO_REG_MEM_CRC	= REG_MEM(0x38),
++};
++
++#define GLAMO_MEM_TYPE_MASK	0x03
++
++enum glamo_reg_mem_dram1 {
++	GLAMO_MEM_DRAM1_EN_SDRAM_CLK	= (1 << 11),
++	GLAMO_MEM_DRAM1_SELF_REFRESH	= (1 << 12),
++};
++
++enum glamo_reg_mem_dram2 {
++	GLAMO_MEM_DRAM2_DEEP_PWRDOWN	= (1 << 12),
++};
++
++enum glamo_irq {
++	GLAMO_IRQ_HOSTBUS	= 0x0001,
++	GLAMO_IRQ_JPEG		= 0x0002,
++	GLAMO_IRQ_MPEG		= 0x0004,
++	GLAMO_IRQ_MPROC1	= 0x0008,
++	GLAMO_IRQ_MPROC0	= 0x0010,
++	GLAMO_IRQ_CMDQUEUE	= 0x0020,
++	GLAMO_IRQ_2D		= 0x0040,
++	GLAMO_IRQ_MMC		= 0x0080,
++	GLAMO_IRQ_RISC		= 0x0100,
++};
++
++enum glamo_reg_clock_host {
++	GLAMO_CLOCK_HOST_DG_BCLK	= 0x0001,
++	GLAMO_CLOCK_HOST_DG_M0CLK	= 0x0004,
++	GLAMO_CLOCK_HOST_RESET		= 0x1000,
++};
++
++enum glamo_reg_clock_mem {
++	GLAMO_CLOCK_MEM_DG_M1CLK	= 0x0001,
++	GLAMO_CLOCK_MEM_EN_M1CLK	= 0x0002,
++	GLAMO_CLOCK_MEM_DG_MOCACLK	= 0x0004,
++	GLAMO_CLOCK_MEM_EN_MOCACLK	= 0x0008,
++	GLAMO_CLOCK_MEM_RESET		= 0x1000,
++	GLAMO_CLOCK_MOCA_RESET		= 0x2000,
++};
++
++enum glamo_reg_clock_lcd {
++	GLAMO_CLOCK_LCD_DG_DCLK		= 0x0001,
++	GLAMO_CLOCK_LCD_EN_DCLK		= 0x0002,
++	GLAMO_CLOCK_LCD_DG_DMCLK	= 0x0004,
++	GLAMO_CLOCK_LCD_EN_DMCLK	= 0x0008,
++	//
++	GLAMO_CLOCK_LCD_EN_DHCLK	= 0x0020,
++	GLAMO_CLOCK_LCD_DG_M5CLK	= 0x0040,
++	GLAMO_CLOCK_LCD_EN_M5CLK	= 0x0080,
++	GLAMO_CLOCK_LCD_RESET		= 0x1000,
++};
++
++enum glamo_reg_clock_mmc {
++	GLAMO_CLOCK_MMC_DG_TCLK		= 0x0001,
++	GLAMO_CLOCK_MMC_EN_TCLK		= 0x0002,
++	GLAMO_CLOCK_MMC_DG_M9CLK	= 0x0004,
++	GLAMO_CLOCK_MMC_EN_M9CLK	= 0x0008,
++	GLAMO_CLOCK_MMC_RESET		= 0x1000,
++};
++
++enum glamo_reg_clock_isp {
++	GLAMO_CLOCK_ISP_DG_I1CLK	= 0x0001,
++	GLAMO_CLOCK_ISP_EN_I1CLK	= 0x0002,
++	GLAMO_CLOCK_ISP_DG_CCLK		= 0x0004,
++	GLAMO_CLOCK_ISP_EN_CCLK		= 0x0008,
++	//
++	GLAMO_CLOCK_ISP_EN_SCLK		= 0x0020,
++	GLAMO_CLOCK_ISP_DG_M2CLK	= 0x0040,
++	GLAMO_CLOCK_ISP_EN_M2CLK	= 0x0080,
++	GLAMO_CLOCK_ISP_DG_M15CLK	= 0x0100,
++	GLAMO_CLOCK_ISP_EN_M15CLK	= 0x0200,
++	GLAMO_CLOCK_ISP1_RESET		= 0x1000,
++	GLAMO_CLOCK_ISP2_RESET		= 0x2000,
++};
++
++enum glamo_reg_clock_jpeg {
++	GLAMO_CLOCK_JPEG_DG_JCLK	= 0x0001,
++	GLAMO_CLOCK_JPEG_EN_JCLK	= 0x0002,
++	GLAMO_CLOCK_JPEG_DG_M3CLK	= 0x0004,
++	GLAMO_CLOCK_JPEG_EN_M3CLK	= 0x0008,
++	GLAMO_CLOCK_JPEG_RESET		= 0x1000,
++};
++
++enum glamo_reg_clock_2d {
++	GLAMO_CLOCK_2D_DG_GCLK		= 0x0001,
++	GLAMO_CLOCK_2D_EN_GCLK		= 0x0002,
++	GLAMO_CLOCK_2D_DG_M7CLK		= 0x0004,
++	GLAMO_CLOCK_2D_EN_M7CLK		= 0x0008,
++	GLAMO_CLOCK_2D_DG_M6CLK		= 0x0010,
++	GLAMO_CLOCK_2D_EN_M6CLK		= 0x0020,
++	GLAMO_CLOCK_2D_RESET		= 0x1000,
++	GLAMO_CLOCK_2D_CQ_RESET		= 0x2000,
++};
++
++enum glamo_reg_clock_3d {
++	GLAMO_CLOCK_3D_DG_ECLK		= 0x0001,
++	GLAMO_CLOCK_3D_EN_ECLK		= 0x0002,
++	GLAMO_CLOCK_3D_DG_RCLK		= 0x0004,
++	GLAMO_CLOCK_3D_EN_RCLK		= 0x0008,
++	GLAMO_CLOCK_3D_DG_M8CLK		= 0x0010,
++	GLAMO_CLOCK_3D_EN_M8CLK		= 0x0020,
++	GLAMO_CLOCK_3D_BACK_RESET	= 0x1000,
++	GLAMO_CLOCK_3D_FRONT_RESET	= 0x2000,
++};
++
++enum glamo_reg_clock_mpeg {
++	GLAMO_CLOCK_MPEG_DG_X0CLK	= 0x0001,
++	GLAMO_CLOCK_MPEG_EN_X0CLK	= 0x0002,
++	GLAMO_CLOCK_MPEG_DG_X1CLK	= 0x0004,
++	GLAMO_CLOCK_MPEG_EN_X1CLK	= 0x0008,
++	GLAMO_CLOCK_MPEG_DG_X2CLK	= 0x0010,
++	GLAMO_CLOCK_MPEG_EN_X2CLK	= 0x0020,
++	GLAMO_CLOCK_MPEG_DG_X3CLK	= 0x0040,
++	GLAMO_CLOCK_MPEG_EN_X3CLK	= 0x0080,
++	GLAMO_CLOCK_MPEG_DG_X4CLK	= 0x0100,
++	GLAMO_CLOCK_MPEG_EN_X4CLK	= 0x0200,
++	GLAMO_CLOCK_MPEG_DG_X6CLK	= 0x0400,
++	GLAMO_CLOCK_MPEG_EN_X6CLK	= 0x0800,
++	GLAMO_CLOCK_MPEG_ENC_RESET	= 0x1000,
++	GLAMO_CLOCK_MPEG_DEC_RESET	= 0x2000,
++};
++
++enum glamo_reg_clock51 {
++	GLAMO_CLOCK_GEN51_EN_DIV_MCLK	= 0x0001,
++	GLAMO_CLOCK_GEN51_EN_DIV_SCLK	= 0x0002,
++	GLAMO_CLOCK_GEN51_EN_DIV_JCLK	= 0x0004,
++	GLAMO_CLOCK_GEN51_EN_DIV_DCLK	= 0x0008,
++	GLAMO_CLOCK_GEN51_EN_DIV_DMCLK	= 0x0010,
++	GLAMO_CLOCK_GEN51_EN_DIV_DHCLK	= 0x0020,
++	GLAMO_CLOCK_GEN51_EN_DIV_GCLK	= 0x0040,
++	GLAMO_CLOCK_GEN51_EN_DIV_TCLK	= 0x0080,
++	/* FIXME: higher bits */
++};
++
++enum glamo_reg_clock52 {
++	GLAMO_CLOCK_GEN52_EN_DIV_ACLK	= 0x0001,
++	GLAMO_CLOCK_GEN52_EN_DIV_AMCLK	= 0x0002,
++	GLAMO_CLOCK_GEN52_EN_DIV_OCLK	= 0x0004,
++	GLAMO_CLOCK_GEN52_EN_DIV_ZCLK	= 0x0008,
++	GLAMO_CLOCK_GEN52_EN_DIV_ICLK	= 0x0010,
++	/* FIXME: higher bits */
++};
++
++enum glamo_reg_hostbus2 {
++	GLAMO_HOSTBUS2_MMIO_EN_ISP	= 0x0001,
++	GLAMO_HOSTBUS2_MMIO_EN_JPEG	= 0x0002,
++	GLAMO_HOSTBUS2_MMIO_EN_MPEG	= 0x0004,
++	GLAMO_HOSTBUS2_MMIO_EN_LCD	= 0x0008,
++	GLAMO_HOSTBUS2_MMIO_EN_MMC	= 0x0010,
++	GLAMO_HOSTBUS2_MMIO_EN_MICROP0	= 0x0020,
++	GLAMO_HOSTBUS2_MMIO_EN_MICROP1	= 0x0040,
++	GLAMO_HOSTBUS2_MMIO_EN_CQ	= 0x0080,
++	GLAMO_HOSTBUS2_MMIO_EN_RISC	= 0x0100,
++	GLAMO_HOSTBUS2_MMIO_EN_2D	= 0x0200,
++	GLAMO_HOSTBUS2_MMIO_EN_3D	= 0x0400,
++};
++
++/* LCD Controller */
++
++#define REG_LCD(x)	(x)
++enum glamo_reg_lcd {
++	GLAMO_REG_LCD_MODE1		= REG_LCD(0x00),
++	GLAMO_REG_LCD_MODE2		= REG_LCD(0x02),
++	GLAMO_REG_LCD_MODE3		= REG_LCD(0x04),
++	GLAMO_REG_LCD_WIDTH		= REG_LCD(0x06),
++	GLAMO_REG_LCD_HEIGHT		= REG_LCD(0x08),
++	GLAMO_REG_LCD_POLARITY		= REG_LCD(0x0a),
++	GLAMO_REG_LCD_A_BASE1		= REG_LCD(0x0c),
++	GLAMO_REG_LCD_A_BASE2		= REG_LCD(0x0e),
++	GLAMO_REG_LCD_B_BASE1		= REG_LCD(0x10),
++	GLAMO_REG_LCD_B_BASE2		= REG_LCD(0x12),
++	GLAMO_REG_LCD_C_BASE1		= REG_LCD(0x14),
++	GLAMO_REG_LCD_C_BASE2		= REG_LCD(0x16),
++	GLAMO_REG_LCD_PITCH		= REG_LCD(0x18),
++	/* RES */
++	GLAMO_REG_LCD_HORIZ_TOTAL	= REG_LCD(0x1c),
++	/* RES */
++	GLAMO_REG_LCD_HORIZ_RETR_START	= REG_LCD(0x20),
++	/* RES */
++	GLAMO_REG_LCD_HORIZ_RETR_END	= REG_LCD(0x24),
++	/* RES */
++	GLAMO_REG_LCD_HORIZ_DISP_START	= REG_LCD(0x28),
++	/* RES */
++	GLAMO_REG_LCD_HORIZ_DISP_END	= REG_LCD(0x2c),
++	/* RES */
++	GLAMO_REG_LCD_VERT_TOTAL	= REG_LCD(0x30),
++	/* RES */
++	GLAMO_REG_LCD_VERT_RETR_START	= REG_LCD(0x34),
++	/* RES */
++	GLAMO_REG_LCD_VERT_RETR_END	= REG_LCD(0x38),
++	/* RES */
++	GLAMO_REG_LCD_VERT_DISP_START	= REG_LCD(0x3c),
++	/* RES */
++	GLAMO_REG_LCD_VERT_DISP_END	= REG_LCD(0x40),
++	/* RES */
++	GLAMO_REG_LCD_POL		= REG_LCD(0x44),
++	GLAMO_REG_LCD_DATA_START	= REG_LCD(0x46),
++	GLAMO_REG_LCD_FRATE_CONTRO	= REG_LCD(0x48),
++	GLAMO_REG_LCD_DATA_CMD_HDR	= REG_LCD(0x4a),
++	GLAMO_REG_LCD_SP_START		= REG_LCD(0x4c),
++	GLAMO_REG_LCD_SP_END		= REG_LCD(0x4e),
++	GLAMO_REG_LCD_CURSOR_BASE1	= REG_LCD(0x50),
++	GLAMO_REG_LCD_CURSOR_BASE2	= REG_LCD(0x52),
++	GLAMO_REG_LCD_CURSOR_PITCH	= REG_LCD(0x54),
++	GLAMO_REG_LCD_CURSOR_X_SIZE	= REG_LCD(0x56),
++	GLAMO_REG_LCD_CURSOR_Y_SIZE	= REG_LCD(0x58),
++	GLAMO_REG_LCD_CURSOR_X_POS	= REG_LCD(0x5a),
++	GLAMO_REG_LCD_CURSOR_Y_POS	= REG_LCD(0x5c),
++	GLAMO_REG_LCD_CURSOR_PRESET	= REG_LCD(0x5e),
++	GLAMO_REG_LCD_CURSOR_FG_COLOR	= REG_LCD(0x60),
++	/* RES */
++	GLAMO_REG_LCD_CURSOR_BG_COLOR	= REG_LCD(0x64),
++	/* RES */
++	GLAMO_REG_LCD_CURSOR_DST_COLOR	= REG_LCD(0x68),
++	/* RES */
++	GLAMO_REG_LCD_STATUS1		= REG_LCD(0x80),
++	GLAMO_REG_LCD_STATUS2		= REG_LCD(0x82),
++	GLAMO_REG_LCD_STATUS3		= REG_LCD(0x84),
++	GLAMO_REG_LCD_STATUS4		= REG_LCD(0x86),
++	/* RES */
++	GLAMO_REG_LCD_COMMAND1		= REG_LCD(0xa0),
++	GLAMO_REG_LCD_COMMAND2		= REG_LCD(0xa2),
++	/* RES */
++	GLAMO_REG_LCD_WFORM_DELAY1	= REG_LCD(0xb0),
++	GLAMO_REG_LCD_WFORM_DELAY2	= REG_LCD(0xb2),
++	/* RES */
++	GLAMO_REG_LCD_GAMMA_CORR	= REG_LCD(0x100),
++	/* RES */
++	GLAMO_REG_LCD_GAMMA_R_ENTRY01	= REG_LCD(0x110),
++	GLAMO_REG_LCD_GAMMA_R_ENTRY23	= REG_LCD(0x112),
++	GLAMO_REG_LCD_GAMMA_R_ENTRY45	= REG_LCD(0x114),
++	GLAMO_REG_LCD_GAMMA_R_ENTRY67	= REG_LCD(0x116),
++	GLAMO_REG_LCD_GAMMA_R_ENTRY8	= REG_LCD(0x118),
++	/* RES */
++	GLAMO_REG_LCD_GAMMA_G_ENTRY01	= REG_LCD(0x130),
++	GLAMO_REG_LCD_GAMMA_G_ENTRY23	= REG_LCD(0x132),
++	GLAMO_REG_LCD_GAMMA_G_ENTRY45	= REG_LCD(0x134),
++	GLAMO_REG_LCD_GAMMA_G_ENTRY67	= REG_LCD(0x136),
++	GLAMO_REG_LCD_GAMMA_G_ENTRY8	= REG_LCD(0x138),
++	/* RES */
++	GLAMO_REG_LCD_GAMMA_B_ENTRY01	= REG_LCD(0x150),
++	GLAMO_REG_LCD_GAMMA_B_ENTRY23	= REG_LCD(0x152),
++	GLAMO_REG_LCD_GAMMA_B_ENTRY45	= REG_LCD(0x154),
++	GLAMO_REG_LCD_GAMMA_B_ENTRY67	= REG_LCD(0x156),
++	GLAMO_REG_LCD_GAMMA_B_ENTRY8	= REG_LCD(0x158),
++	/* RES */
++	GLAMO_REG_LCD_SRAM_DRIVING1	= REG_LCD(0x160),
++	GLAMO_REG_LCD_SRAM_DRIVING2	= REG_LCD(0x162),
++	GLAMO_REG_LCD_SRAM_DRIVING3	= REG_LCD(0x164),
++};
++
++enum glamo_reg_lcd_mode1 {
++	GLAMO_LCD_MODE1_PWRSAVE		= 0x0001,
++	GLAMO_LCD_MODE1_PARTIAL_PRT	= 0x0002,
++	GLAMO_LCD_MODE1_HWFLIP		= 0x0004,
++	GLAMO_LCD_MODE1_LCD2		= 0x0008,
++	/* RES */
++	GLAMO_LCD_MODE1_PARTIAL_MODE	= 0x0020,
++	GLAMO_LCD_MODE1_CURSOR_DSTCOLOR	= 0x0040,
++	GLAMO_LCD_MODE1_PARTIAL_ENABLE	= 0x0080,
++	GLAMO_LCD_MODE1_TVCLK_IN_ENABLE	= 0x0100,
++	GLAMO_LCD_MODE1_HSYNC_HIGH_ACT	= 0x0200,
++	GLAMO_LCD_MODE1_VSYNC_HIGH_ACT	= 0x0400,
++	GLAMO_LCD_MODE1_HSYNC_FLIP	= 0x0800,
++	GLAMO_LCD_MODE1_GAMMA_COR_EN	= 0x1000,
++	GLAMO_LCD_MODE1_DITHER_EN	= 0x2000,
++	GLAMO_LCD_MODE1_CURSOR_EN	= 0x4000,
++	GLAMO_LCD_MODE1_ROTATE_EN	= 0x8000,
++};
++
++enum glamo_reg_lcd_mode2 {
++	GLAMO_LCD_MODE2_CRC_CHECK_EN	= 0x0001,
++	GLAMO_LCD_MODE2_DCMD_PER_LINE	= 0x0002,
++	GLAMO_LCD_MODE2_NOUSE_BDEF	= 0x0004,
++	GLAMO_LCD_MODE2_OUT_POS_MODE	= 0x0008,
++	GLAMO_LCD_MODE2_FRATE_CTRL_EN	= 0x0010,
++	GLAMO_LCD_MODE2_SINGLE_BUFFER	= 0x0020,
++	GLAMO_LCD_MODE2_SER_LSB_TO_MSB	= 0x0040,
++	/* FIXME */
++};
++
++enum glamo_reg_lcd_mode3 {
++	/* LCD color source data format */
++	GLAMO_LCD_SRC_RGB565		= 0x0000,
++	GLAMO_LCD_SRC_ARGB1555		= 0x4000,
++	GLAMO_LCD_SRC_ARGB4444		= 0x8000,
++	/* interface type */
++	GLAMO_LCD_MODE3_LCD		= 0x1000,
++	GLAMO_LCD_MODE3_RGB		= 0x0800,
++	GLAMO_LCD_MODE3_CPU		= 0x0000,
++	/* mode */
++	GLAMO_LCD_MODE3_RGB332		= 0x0000,
++	GLAMO_LCD_MODE3_RGB444		= 0x0100,
++	GLAMO_LCD_MODE3_RGB565		= 0x0200,
++	GLAMO_LCD_MODE3_RGB666		= 0x0300,
++	/* depth */
++	GLAMO_LCD_MODE3_6BITS		= 0x0000,
++	GLAMO_LCD_MODE3_8BITS		= 0x0010,
++	GLAMO_LCD_MODE3_9BITS		= 0x0020,
++	GLAMO_LCD_MODE3_16BITS		= 0x0030,
++	GLAMO_LCD_MODE3_18BITS		= 0x0040,
++};
++
++enum glamo_lcd_cmd_type {
++	GLAMO_LCD_CMD_TYPE_DISP		= 0x0000,
++	GLAMO_LCD_CMD_TYPE_PARALLEL	= 0x4000,
++	GLAMO_LCD_CMD_TYPE_SERIAL	= 0x8000,
++	GLAMO_LCD_CMD_TYPE_SERIAL_DIRECT= 0xc000,
++};
++#define GLAMO_LCD_CMD_TYPE_MASK		0xc000
++
++enum glamo_lcd_cmds {
++	GLAMO_LCD_CMD_DATA_DISP_FIRE	= 0x00,
++	GLAMO_LCD_CMD_DATA_DISP_SYNC	= 0x01,		/* RGB only */
++	/* switch to command mode, no display */
++	GLAMO_LCD_CMD_DATA_FIRE_NO_DISP	= 0x02,
++	/* display until VSYNC, switch to command */
++	GLAMO_LCD_CMD_DATA_FIRE_VSYNC	= 0x11,
++	/* display until HSYNC, switch to command */
++	GLAMO_LCD_CMD_DATA_FIRE_HSYNC	= 0x12,
++	/* display until VSYNC, 1 black frame, VSYNC, switch to command */
++	GLAMO_LCD_CMD_DATA_FIRE_VSYNC_B	= 0x13,
++	/* don't care about display and switch to command */
++	GLAMO_LCD_CMD_DATA_FIRE_FREE	= 0x14,		/* RGB only */
++	/* don't care about display, keep data display but disable data,
++	 * and switch to command */
++	GLAMO_LCD_CMD_DATA_FIRE_FREE_D	= 0x15,		/* RGB only */
++};
++
++enum glamo_core_revisions {
++	GLAMO_CORE_REV_A0		= 0x0000,
++	GLAMO_CORE_REV_A1		= 0x0001,
++	GLAMO_CORE_REV_A2		= 0x0002,
++	GLAMO_CORE_REV_A3		= 0x0003,
++};
++
++#define REG_ISP(x)		(GLAMO_REGOFS_ISP+(x))
++
++enum glamo_register_isp {
++	GLAMO_REG_ISP_EN1		= REG_ISP(0x00),
++	GLAMO_REG_ISP_EN2		= REG_ISP(0x02),
++	GLAMO_REG_ISP_EN3		= REG_ISP(0x04),
++	GLAMO_REG_ISP_EN4		= REG_ISP(0x06),
++	GLAMO_REG_ISP_CAP_0_ADDRL	= REG_ISP(0x08),
++	GLAMO_REG_ISP_CAP_0_ADDRH	= REG_ISP(0x0a),
++	GLAMO_REG_ISP_CAP_1_ADDRL	= REG_ISP(0x0c),
++	GLAMO_REG_ISP_CAP_1_ADDRH	= REG_ISP(0x0e),
++	GLAMO_REG_ISP_DEC_Y_ADDRL	= REG_ISP(0x10),
++	GLAMO_REG_ISP_DEC_Y_ADDRH	= REG_ISP(0x12),
++	GLAMO_REG_ISP_DEC_U_ADDRL	= REG_ISP(0x14),
++	GLAMO_REG_ISP_DEC_U_ADDRH	= REG_ISP(0x16),
++	GLAMO_REG_ISP_DEC_V_ADDRL	= REG_ISP(0x18),
++	GLAMO_REG_ISP_DEC_V_ADDRH	= REG_ISP(0x1a),
++	GLAMO_REG_ISP_CAP_SEG_HEIGHT	= REG_ISP(0x1c),
++	GLAMO_REG_ISP_CAP_PITCH		= REG_ISP(0x1e),
++	GLAMO_REG_ISP_CAP_HEIGHT	= REG_ISP(0x20),
++	GLAMO_REG_ISP_CAP_WIDTH		= REG_ISP(0x22),
++	GLAMO_REG_ISP_DEC_PITCH_Y	= REG_ISP(0x24),
++	GLAMO_REG_ISP_DEC_PITCH_UV	= REG_ISP(0x26),
++	GLAMO_REG_ISP_DEC_HEIGHT	= REG_ISP(0x28),
++	GLAMO_REG_ISP_DEC_WIDTH		= REG_ISP(0x2a),
++	GLAMO_REG_ISP_ONFLY_MODE1	= REG_ISP(0x2c),
++	GLAMO_REG_ISP_ONFLY_MODE2	= REG_ISP(0x2e),
++	GLAMO_REG_ISP_ONFLY_MODE3	= REG_ISP(0x30),
++	GLAMO_REG_ISP_ONFLY_MODE4	= REG_ISP(0x32),
++	GLAMO_REG_ISP_ONFLY_MODE5	= REG_ISP(0x34),
++	//
++	GLAMO_REG_ISP_YUV2RGB_11	= REG_ISP(0x50),
++	GLAMO_REG_ISP_YUV2RGB_21	= REG_ISP(0x52),
++	GLAMO_REG_ISP_YUV2RGB_32	= REG_ISP(0x54),
++	GLAMO_REG_ISP_YUV2RGB_33	= REG_ISP(0x56),
++	GLAMO_REG_ISP_YUV2RGB_RG	= REG_ISP(0x58),
++	GLAMO_REG_ISP_YUV2RGB_B		= REG_ISP(0x5a),
++	//
++	GLAMO_REG_ISP_PORT1_SCALEH	= REG_ISP(0x76),
++	GLAMO_REG_ISP_PORT1_SCALEV	= REG_ISP(0x78),
++	GLAMO_REG_ISP_PORT2_SCALEH	= REG_ISP(0x7a),
++	GLAMO_REG_ISP_PORT2_SCALEV	= REG_ISP(0x7c),
++	GLAMO_REG_ISP_DEC_SCALEH	= REG_ISP(0x7e),
++	GLAMO_REG_ISP_DEC_SCALEV	= REG_ISP(0x80),
++	GLAMO_REG_ISP_TURBO		= REG_ISP(0x82),
++	GLAMO_REG_ISP_PORT1_CAP_EN	= REG_ISP(0x84),
++	GLAMO_REG_ISP_PORT1_CAP_0_ADDRL	= REG_ISP(0x86),
++	GLAMO_REG_ISP_PORT1_CAP_0_ADDRH	= REG_ISP(0x88),
++	GLAMO_REG_ISP_PORT1_CAP_1_ADDRL	= REG_ISP(0x8a),
++	GLAMO_REG_ISP_PORT1_CAP_1_ADDRH	= REG_ISP(0x8c),
++	GLAMO_REG_ISP_PORT1_CAP_WIDTH	= REG_ISP(0x8e),
++	GLAMO_REG_ISP_PORT1_CAP_HEIGHT	= REG_ISP(0x90),
++	GLAMO_REG_ISP_PORT1_CAP_PITCH	= REG_ISP(0x92),
++	GLAMO_REG_ISP_PORT1_CAP_CLIP_L	= REG_ISP(0x94),
++	GLAMO_REG_ISP_PORT1_CAP_CLIP_R	= REG_ISP(0x96),
++	GLAMO_REG_ISP_PORT1_CAP_CLIP_T	= REG_ISP(0x98),
++	GLAMO_REG_ISP_PORT1_CAP_CLIP_B	= REG_ISP(0x9a),
++	GLAMO_REG_ISP_PORT1_DEC_EN	= REG_ISP(0x9c),
++	GLAMO_REG_ISP_PORT1_DEC_0_ADDRL	= REG_ISP(0x9e),
++	GLAMO_REG_ISP_PORT1_DEC_0_ADDRH	= REG_ISP(0xa0),
++	GLAMO_REG_ISP_PORT1_DEC_1_ADDRL	= REG_ISP(0xa2),
++	GLAMO_REG_ISP_PORT1_DEC_1_ADDRH	= REG_ISP(0xa4),
++	GLAMO_REG_ISP_PORT1_DEC_WIDTH	= REG_ISP(0xa6),
++	GLAMO_REG_ISP_PORT1_DEC_HEIGHT	= REG_ISP(0xa8),
++	GLAMO_REG_ISP_PORT1_DEC_PITCH	= REG_ISP(0xaa),
++	GLAMO_REG_ISP_PORT1_DEC_CLIP_L	= REG_ISP(0xac),
++	GLAMO_REG_ISP_PORT1_DEC_CLIP_R	= REG_ISP(0xae),
++	GLAMO_REG_ISP_PORT1_DEC_CLIP_T	= REG_ISP(0xb0),
++	GLAMO_REG_ISP_PORT1_DEC_CLIP_B	= REG_ISP(0xb2),
++	GLAMO_REG_ISP_PORT2_EN		= REG_ISP(0xb4),
++	GLAMO_REG_ISP_PORT2_0_Y_ADDRL	= REG_ISP(0xb6),
++	GLAMO_REG_ISP_PORT2_0_Y_ADDRH	= REG_ISP(0xb8),
++	GLAMO_REG_ISP_PORT2_0_U_ADDRL	= REG_ISP(0xba),
++	GLAMO_REG_ISP_PORT2_0_U_ADDRH	= REG_ISP(0xbc),
++	GLAMO_REG_ISP_PORT2_0_V_ADDRL	= REG_ISP(0xbe),
++	GLAMO_REG_ISP_PORT2_0_V_ADDRH	= REG_ISP(0xc0),
++	GLAMO_REG_ISP_PORT2_1_Y_ADDRL	= REG_ISP(0xc2),
++	GLAMO_REG_ISP_PORT2_1_Y_ADDRH	= REG_ISP(0xc4),
++	GLAMO_REG_ISP_PORT2_1_U_ADDRL	= REG_ISP(0xc6),
++	GLAMO_REG_ISP_PORT2_1_U_ADDRH	= REG_ISP(0xc8),
++	GLAMO_REG_ISP_PORT2_1_V_ADDRL	= REG_ISP(0xca),
++	GLAMO_REG_ISP_PORT2_1_V_ADDRH	= REG_ISP(0xcc),
++	GLAMO_REG_ISP_PORT2_2_Y_ADDRL	= REG_ISP(0xce),
++	GLAMO_REG_ISP_PORT2_2_Y_ADDRH	= REG_ISP(0xd0),
++	GLAMO_REG_ISP_PORT2_2_U_ADDRL	= REG_ISP(0xd2),
++	GLAMO_REG_ISP_PORT2_2_U_ADDRH	= REG_ISP(0xd4),
++	GLAMO_REG_ISP_PORT2_2_V_ADDRL	= REG_ISP(0xd6),
++	GLAMO_REG_ISP_PORT2_2_V_ADDRH	= REG_ISP(0xd8),
++	GLAMO_REG_ISP_PORT2_WIDTH	= REG_ISP(0xda),
++	GLAMO_REG_ISP_PORT2_HEIGHT	= REG_ISP(0xdc),
++	GLAMO_REG_ISP_PORT2_Y_PITCH	= REG_ISP(0xde),
++	GLAMO_REG_ISP_PORT2_UV_PITCH	= REG_ISP(0xe0),
++	//
++	GLAMO_REG_ISP_RGB2YUV_11_12	= REG_ISP(0xf6),
++	GLAMO_REG_ISP_RGB2YUV_13_21	= REG_ISP(0xf8),
++	GLAMO_REG_ISP_RGB2YUV_22_23	= REG_ISP(0xfa),
++	GLAMO_REG_ISP_RGB2YUV_31_32	= REG_ISP(0xfc),
++	GLAMO_REG_ISP_RGB2YUV_33	= REG_ISP(0xfe),
++	//
++	GLAMO_REG_ISP_PORT1_SCALEH_MATRIX	= REG_ISP(0x10c),
++	//
++	GLAMO_REG_ISP_PORT1_SCALEV_MATRIX	= REG_ISP(0x120),
++	//
++	GLAMO_REG_ISP_PORT2_SCALEH_MATRIX	= REG_ISP(0x134),
++	//
++	GLAMO_REG_ISP_PORT2_SCALEV_MATRIX	= REG_ISP(0x148),
++	//
++	GLAMO_REG_ISP_DEC_SCALEH_MATRIX		= REG_ISP(0x15c),
++	//
++	GLAMO_REG_ISP_DEC_SCALEV_MATRIX		= REG_ISP(0x170),
++	//
++	GLAMO_REG_ISP_STATUS			= REG_ISP(0x184),
++};
++
++enum glamo_reg_isp_en1 {
++	GLAMO_ISP_EN1_FIRE_ISP		= 0x0001,
++	GLAMO_ISP_EN1_FIRE_CAP		= 0x0002,
++	GLAMO_ISP_EN1_VIDEO_CONF	= 0x0004,
++	GLAMO_ISP_EN1_BAYER_SRC		= 0x0008,
++	//
++	GLAMO_ISP_EN1_YUV_PACK		= 0x0040,
++	GLAMO_ISP_EN1_PLANE_MODE	= 0x0080,
++	GLAMO_ISP_EN1_YUV_INPUT		= 0x0100,
++	GLAMO_ISP_EN1_YUV420		= 0x0200,
++	//
++};
++
++enum glamo_reg_isp_en3 {
++	//
++	GLAMO_ISP_EN3_SCALE_IMPROVE	= 0x0040,
++	GLAMO_ISP_EN3_PLANE_MODE	= 0x0080,
++	GLAMO_ISP_EN3_YUV_INPUT		= 0x0100,
++	GLAMO_ISP_EN3_YUV420		= 0x0200,
++	//
++};
++
++enum glamo_reg_isp_port1_en {
++	GLAMO_ISP_PORT1_EN_OUTPUT	= 0x0001,
++//	GLAMO_ISP_PORT1_EN_SCALE	= 0x0002,
++	GLAMO_ISP_PORT1_EN_CLIP		= 0x0004,
++	GLAMO_ISP_PORT1_EN_CLIP_OUT	= 0x0008,
++	GLAMO_ISP_PORT1_EN_DUAL_BUF	= 0x0010,
++};
++
++enum glamo_reg_isp_port2_en {
++	GLAMO_ISP_PORT2_EN_OUTPUT	= 0x0001,
++	GLAMO_ISP_PORT2_EN_SCALE	= 0x0002,
++	GLAMO_ISP_PORT2_EN_JPEG		= 0x0010,
++	GLAMO_ISP_PORT2_EN_MPEG		= 0x0020,
++	GLAMO_ISP_PORT2_EN_ENCODE	= 0x0040,
++	GLAMO_ISP_PORT2_EN_DECODE	= 0x0080,
++};
++
++#define REG_CQ(x)		(GLAMO_REGOFS_CMDQUEUE+(x))
++
++enum glamo_register_cq {
++	GLAMO_REG_CQ_BASE_ADDRL		= REG_CQ(0x00),
++	GLAMO_REG_CQ_BASE_ADDRH		= REG_CQ(0x02),
++	GLAMO_REG_CQ_LEN		= REG_CQ(0x04),
++	GLAMO_REG_CQ_WRITE_ADDRL	= REG_CQ(0x06),
++	GLAMO_REG_CQ_WRITE_ADDRH	= REG_CQ(0x08),
++	GLAMO_REG_CQ_FLIP		= REG_CQ(0x0a),
++	GLAMO_REG_CQ_CONTROL		= REG_CQ(0x0c),
++	GLAMO_REG_CQ_READ_ADDRL		= REG_CQ(0x0e),
++	GLAMO_REG_CQ_READ_ADDRH		= REG_CQ(0x10),
++	GLAMO_REG_CQ_STATUS		= REG_CQ(0x12),
++};
++
++#define REG_2D(x)		(GLAMO_REGOFS_2D+(x))
++
++enum glamo_register_2d {
++	GLAMO_REG_2D_SRC_ADDRL		= REG_2D(0x00),
++	GLAMO_REG_2D_SRC_ADDRH		= REG_2D(0x02),
++	GLAMO_REG_2D_SRC_PITCH		= REG_2D(0x04),
++	GLAMO_REG_2D_SRC_X		= REG_2D(0x06),
++	GLAMO_REG_2D_SRC_Y		= REG_2D(0x08),
++	GLAMO_REG_2D_DST_X		= REG_2D(0x0a),
++	GLAMO_REG_2D_DST_Y		= REG_2D(0x0c),
++	GLAMO_REG_2D_DST_ADDRL		= REG_2D(0x0e),
++	GLAMO_REG_2D_DST_ADDRH		= REG_2D(0x10),
++	GLAMO_REG_2D_DST_PITCH		= REG_2D(0x12),
++	GLAMO_REG_2D_DST_HEIGHT		= REG_2D(0x14),
++	GLAMO_REG_2D_RECT_WIDTH		= REG_2D(0x16),
++	GLAMO_REG_2D_RECT_HEIGHT	= REG_2D(0x18),
++	GLAMO_REG_2D_PAT_ADDRL		= REG_2D(0x1a),
++	GLAMO_REG_2D_PAT_ADDRH		= REG_2D(0x1c),
++	GLAMO_REG_2D_PAT_FG		= REG_2D(0x1e),
++	GLAMO_REG_2D_PAT_BG		= REG_2D(0x20),
++	GLAMO_REG_2D_SRC_FG		= REG_2D(0x22),
++	GLAMO_REG_2D_SRC_BG		= REG_2D(0x24),
++	GLAMO_REG_2D_MASK1		= REG_2D(0x26),
++	GLAMO_REG_2D_MASK2		= REG_2D(0x28),
++	GLAMO_REG_2D_MASK3		= REG_2D(0x2a),
++	GLAMO_REG_2D_MASK4		= REG_2D(0x2c),
++	GLAMO_REG_2D_ROT_X		= REG_2D(0x2e),
++	GLAMO_REG_2D_ROT_Y		= REG_2D(0x30),
++	GLAMO_REG_2D_LEFT_CLIP		= REG_2D(0x32),
++	GLAMO_REG_2D_TOP_CLIP		= REG_2D(0x34),
++	GLAMO_REG_2D_RIGHT_CLIP		= REG_2D(0x36),
++	GLAMO_REG_2D_BOTTOM_CLIP	= REG_2D(0x38),
++	GLAMO_REG_2D_COMMAND1		= REG_2D(0x3A),
++	GLAMO_REG_2D_COMMAND2		= REG_2D(0x3C),
++	GLAMO_REG_2D_COMMAND3		= REG_2D(0x3E),
++	GLAMO_REG_2D_SAFE		= REG_2D(0x40),
++	GLAMO_REG_2D_STATUS		= REG_2D(0x42),
++	GLAMO_REG_2D_ID1		= REG_2D(0x44),
++	GLAMO_REG_2D_ID2		= REG_2D(0x46),
++	GLAMO_REG_2D_ID3		= REG_2D(0x48),
++};
++
++#endif /* _GLAMO_REGS_H */
+Index: xserver/hw/kdrive/glamo/glamo.c
+===================================================================
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ xserver/hw/kdrive/glamo/glamo.c	2007-09-26 17:44:47.000000000 +0800
+@@ -0,0 +1,498 @@
++/*
++ * Copyright © 2007 OpenMoko, Inc.
++ *
++ * This driver is based on Xati,
++ * Copyright © 2003 Eric Anholt
++ *
++ * Permission to use, copy, modify, distribute, and sell this software and its
++ * documentation for any purpose is hereby granted without fee, provided that
++ * the above copyright notice appear in all copies and that both that copyright
++ * notice and this permission notice appear in supporting documentation, and
++ * that the name of the copyright holders not be used in advertising or
++ * publicity pertaining to distribution of the software without specific,
++ * written prior permission.  The copyright holders make no representations
++ * about the suitability of this software for any purpose.  It is provided "as
++ * is" without express or implied warranty.
++ *
++ * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
++ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
++ * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
++ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
++ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
++ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
++ * OF THIS SOFTWARE.
++ */
++
++#ifdef HAVE_CONFIG_H
++#include <kdrive-config.h>
++#endif
++#include "glamo.h"
++#if defined(USE_DRI) && defined(GLXEXT)
++#include "glamo_sarea.h"
++#endif
++
++static Bool
++GLAMOCardInit(KdCardInfo *card)
++{
++	GLAMOCardInfo *glamoc;
++	Bool initialized = FALSE;
++
++	glamoc = xcalloc(sizeof(GLAMOCardInfo), 1);
++	if (glamoc == NULL)
++		return FALSE;
++
++#ifdef KDRIVEFBDEV
++	if (!initialized && fbdevInitialize(card, &glamoc->backend_priv.fbdev)) {
++		glamoc->use_fbdev = TRUE;
++		initialized = TRUE;
++		glamoc->backend_funcs.cardfini = fbdevCardFini;
++		glamoc->backend_funcs.scrfini = fbdevScreenFini;
++		glamoc->backend_funcs.initScreen = fbdevInitScreen;
++		glamoc->backend_funcs.finishInitScreen = fbdevFinishInitScreen;
++		glamoc->backend_funcs.createRes = fbdevCreateResources;
++		glamoc->backend_funcs.preserve = fbdevPreserve;
++		glamoc->backend_funcs.restore = fbdevRestore;
++		glamoc->backend_funcs.dpms = fbdevDPMS;
++		glamoc->backend_funcs.enable = fbdevEnable;
++		glamoc->backend_funcs.disable = fbdevDisable;
++		glamoc->backend_funcs.getColors = fbdevGetColors;
++		glamoc->backend_funcs.putColors = fbdevPutColors;
++#ifdef RANDR
++		glamoc->backend_funcs.randrSetConfig = fbdevRandRSetConfig;
++#endif
++	}
++#endif
++#ifdef KDRIVEVESA
++	if (!initialized && vesaInitialize(card, &glamoc->backend_priv.vesa)) {
++		glamoc->use_vesa = TRUE;
++		initialized = TRUE;
++		glamoc->backend_funcs.cardfini = vesaCardFini;
++		glamoc->backend_funcs.scrfini = vesaScreenFini;
++		glamoc->backend_funcs.initScreen = vesaInitScreen;
++		glamoc->backend_funcs.finishInitScreen = vesaFinishInitScreen;
++		glamoc->backend_funcs.createRes = vesaCreateResources;
++		glamoc->backend_funcs.preserve = vesaPreserve;
++		glamoc->backend_funcs.restore = vesaRestore;
++		glamoc->backend_funcs.dpms = vesaDPMS;
++		glamoc->backend_funcs.enable = vesaEnable;
++		glamoc->backend_funcs.disable = vesaDisable;
++		glamoc->backend_funcs.getColors = vesaGetColors;
++		glamoc->backend_funcs.putColors = vesaPutColors;
++#ifdef RANDR
++		glamoc->backend_funcs.randrSetConfig = vesaRandRSetConfig;
++#endif
++	}
++#endif
++
++	if (!initialized || !GLAMOMapReg(card, glamoc)) {
++		xfree(glamoc);
++		return FALSE;
++	}
++
++#ifdef USE_DRI
++	/* We demand identification by busid, not driver name */
++	glamoc->drmFd = drmOpen(NULL, glamoc->busid);
++	if (glamoc->drmFd < 0)
++		ErrorF("Failed to open DRM, DRI disabled.\n");
++#endif /* USE_DRI */
++
++	card->driver = glamoc;
++
++	glamoc->is_3362 = TRUE;
++	ErrorF("Using GLAMO 3362 card\n");
++
++	return TRUE;
++}
++
++static void
++GLAMOCardFini(KdCardInfo *card)
++{
++	GLAMOCardInfo *glamoc = (GLAMOCardInfo *)card->driver;
++
++	GLAMOUnmapReg(card, glamoc);
++	glamoc->backend_funcs.cardfini(card);
++}
++
++/*
++ * Once screen->off_screen_base is set, this function
++ * allocates the remaining memory appropriately
++ */
++
++static void
++GLAMOSetOffscreen (KdScreenInfo *screen)
++{
++	GLAMOCardInfo(screen);
++#if defined(USE_DRI) && defined(GLXEXT)
++	GLAMOScreenInfo *glamos = (GLAMOScreenInfo *)screen->driver;
++	int l;
++#endif
++	int screen_size;
++	char *mmio = glamoc->reg_base;
++
++	/* check (and adjust) pitch */
++	if (mmio)
++	{
++		int	byteStride = screen->fb[0].byteStride;
++		int	bitStride;
++		int	pixelStride;
++		int	bpp = screen->fb[0].bitsPerPixel;
++
++		/*
++		 * Ensure frame buffer is correctly aligned
++		 */
++		if (byteStride & 0x3f)
++		{
++			byteStride = (byteStride + 0x3f) & ~0x3f;
++			bitStride = byteStride * 8;
++			pixelStride = bitStride / bpp;
++
++			screen->fb[0].byteStride = byteStride;
++			screen->fb[0].pixelStride = pixelStride;
++		}
++	}
++
++	screen_size = screen->fb[0].byteStride * screen->height;
++
++	screen->off_screen_base = screen_size;
++
++#if defined(USE_DRI) && defined(GLXEXT)
++	/* Reserve a static area for the back buffer the same size as the
++	 * visible screen.  XXX: This would be better initialized in glamo_dri.c
++	 * when GLX is set up, but the offscreen memory manager's allocations
++	 * don't last through VT switches, while the kernel's understanding of
++	 * offscreen locations does.
++	 */
++	glamos->frontOffset = 0;
++	glamos->frontPitch = screen->fb[0].byteStride;
++
++	if (screen->off_screen_base + screen_size <= screen->memory_size) {
++		glamos->backOffset = screen->off_screen_base;
++		glamos->backPitch = screen->fb[0].byteStride;
++		screen->off_screen_base += screen_size;
++	}
++
++	/* Reserve the depth span for Rage 128 */
++	if (!glamoc->is_3362 && screen->off_screen_base +
++	    screen->fb[0].byteStride <= screen->memory_size) {
++		glamos->spanOffset = screen->off_screen_base;
++		screen->off_screen_base += screen->fb[0].byteStride;
++	}
++
++	/* Reserve the static depth buffer, which happens to be the same
++	 * bitsPerPixel as the screen.
++	 */
++	if (screen->off_screen_base + screen_size <= screen->memory_size) {
++		glamos->depthOffset = screen->off_screen_base;
++		glamos->depthPitch = screen->fb[0].byteStride;
++		screen->off_screen_base += screen_size;
++	}
++
++	/* Reserve approx. half of remaining offscreen memory for local
++	 * textures.  Round down to a whole number of texture regions.
++	 */
++	glamos->textureSize = (screen->memory_size - screen->off_screen_base) / 2;
++	l = GLAMOLog2(glamos->textureSize / GLAMO_NR_TEX_REGIONS);
++	if (l < GLAMO_LOG_TEX_GRANULARITY)
++		l = GLAMO_LOG_TEX_GRANULARITY;
++	glamos->textureSize = (glamos->textureSize >> l) << l;
++	if (glamos->textureSize >= 512 * 1024) {
++		glamos->textureOffset = screen->off_screen_base;
++		screen->off_screen_base += glamos->textureSize;
++	} else {
++		/* Minimum texture size is for 2 256x256x32bpp textures */
++		glamos->textureSize = 0;
++	}
++#endif /* USE_DRI && GLXEXT */
++}
++
++static Bool
++GLAMOScreenInit(KdScreenInfo *screen)
++{
++	GLAMOScreenInfo *glamos;
++	GLAMOCardInfo(screen);
++	Bool success = FALSE;
++
++	glamos = xcalloc(sizeof(GLAMOScreenInfo), 1);
++	if (glamos == NULL)
++		return FALSE;
++
++	glamos->glamoc = glamoc;
++	glamos->screen = screen;
++	screen->driver = glamos;
++
++	if (screen->fb[0].depth == 0)
++		screen->fb[0].depth = 16;
++#ifdef KDRIVEFBDEV
++	if (glamoc->use_fbdev) {
++		success = fbdevScreenInitialize(screen,
++						&glamos->backend_priv.fbdev);
++	}
++#endif
++#ifdef KDRIVEVESA
++	if (glamoc->use_vesa) {
++		success = vesaScreenInitialize(screen,
++					       &glamos->backend_priv.vesa);
++	}
++#endif
++
++	if (!success) {
++		screen->driver = NULL;
++		xfree(glamos);
++		return FALSE;
++	}
++
++	GLAMOSetOffscreen (screen);
++
++	return TRUE;
++}
++
++#ifdef RANDR
++static Bool
++GLAMORandRSetConfig (ScreenPtr		pScreen,
++		   Rotation		randr,
++		   int			rate,
++		   RRScreenSizePtr	pSize)
++{
++	KdScreenPriv(pScreen);
++	KdScreenInfo *screen = pScreenPriv->screen;
++	GLAMOCardInfo *glamoc = screen->card->driver;
++	Bool ret;
++
++	GLAMODrawDisable (pScreen);
++	ret = glamoc->backend_funcs.randrSetConfig(pScreen, randr, rate, pSize);
++	GLAMOSetOffscreen (screen);
++	/*
++	 * Set frame buffer mapping
++	 */
++	(*pScreen->ModifyPixmapHeader) (fbGetScreenPixmap (pScreen),
++					pScreen->width,
++					pScreen->height,
++					screen->fb[0].depth,
++					screen->fb[0].bitsPerPixel,
++					screen->fb[0].byteStride,
++					screen->fb[0].frameBuffer);
++
++	GLAMODrawEnable (pScreen);
++	return ret;
++}
++
++static Bool
++GLAMORandRInit (ScreenPtr pScreen)
++{
++    rrScrPrivPtr    pScrPriv;
++
++    pScrPriv = rrGetScrPriv(pScreen);
++    pScrPriv->rrSetConfig = GLAMORandRSetConfig;
++    return TRUE;
++}
++#endif
++
++static void
++GLAMOScreenFini(KdScreenInfo *screen)
++{
++	GLAMOScreenInfo *glamos = (GLAMOScreenInfo *)screen->driver;
++	GLAMOCardInfo *glamoc = screen->card->driver;
++
++#ifdef XV
++	GLAMOFiniVideo(screen->pScreen);
++#endif
++
++	glamoc->backend_funcs.scrfini(screen);
++	xfree(glamos);
++	screen->driver = 0;
++}
++
++Bool
++GLAMOMapReg(KdCardInfo *card, GLAMOCardInfo *glamoc)
++{
++	glamoc->reg_base = (char *)KdMapDevice(GLAMO_REG_BASE(card),
++	    GLAMO_REG_SIZE(card));
++
++	if (glamoc->reg_base == NULL)
++		return FALSE;
++
++	KdSetMappedMode(GLAMO_REG_BASE(card), GLAMO_REG_SIZE(card),
++	    KD_MAPPED_MODE_REGISTERS);
++
++	return TRUE;
++}
++
++void
++GLAMOUnmapReg(KdCardInfo *card, GLAMOCardInfo *glamoc)
++{
++	if (glamoc->reg_base) {
++		KdResetMappedMode(GLAMO_REG_BASE(card), GLAMO_REG_SIZE(card),
++		    KD_MAPPED_MODE_REGISTERS);
++		KdUnmapDevice((void *)glamoc->reg_base, GLAMO_REG_SIZE(card));
++		glamoc->reg_base = 0;
++	}
++}
++
++static Bool
++GLAMOInitScreen(ScreenPtr pScreen)
++{
++	KdScreenPriv(pScreen);
++	GLAMOCardInfo(pScreenPriv);
++
++#ifdef XV
++	GLAMOInitVideo(pScreen);
++#endif
++	return glamoc->backend_funcs.initScreen(pScreen);
++}
++
++static Bool
++GLAMOFinishInitScreen(ScreenPtr pScreen)
++{
++	KdScreenPriv(pScreen);
++	GLAMOCardInfo(pScreenPriv);
++
++	if (!glamoc->backend_funcs.finishInitScreen(pScreen))
++		return FALSE;
++#ifdef RANDR
++	if (!GLAMORandRInit (pScreen))
++		return FALSE;
++#endif
++	return TRUE;
++}
++
++static Bool
++GLAMOCreateResources(ScreenPtr pScreen)
++{
++	KdScreenPriv(pScreen);
++	GLAMOCardInfo(pScreenPriv);
++
++	return glamoc->backend_funcs.createRes(pScreen);
++}
++
++static void
++GLAMOPreserve(KdCardInfo *card)
++{
++	GLAMOCardInfo *glamoc = card->driver;
++
++	glamoc->backend_funcs.preserve(card);
++}
++
++static void
++GLAMORestore(KdCardInfo *card)
++{
++	GLAMOCardInfo *glamoc = card->driver;
++
++	GLAMOUnmapReg(card, glamoc);
++
++	glamoc->backend_funcs.restore(card);
++}
++
++static Bool
++GLAMODPMS(ScreenPtr pScreen, int mode)
++{
++	KdScreenPriv(pScreen);
++	GLAMOCardInfo(pScreenPriv);
++
++	return glamoc->backend_funcs.dpms(pScreen, mode);
++}
++
++static Bool
++GLAMOEnable(ScreenPtr pScreen)
++{
++	KdScreenPriv(pScreen);
++	GLAMOCardInfo(pScreenPriv);
++
++	if (!glamoc->backend_funcs.enable(pScreen))
++		return FALSE;
++
++	if ((glamoc->reg_base == NULL) && !GLAMOMapReg(pScreenPriv->screen->card,
++	    glamoc))
++		return FALSE;
++
++	GLAMOSetOffscreen (pScreenPriv->screen);
++
++	return TRUE;
++}
++
++static void
++GLAMODisable(ScreenPtr pScreen)
++{
++	KdScreenPriv(pScreen);
++#if defined(USE_DRI) && defined(GLXEXT)
++	GLAMOScreenInfo(pScreenPriv);
++#endif /* USE_DRI && GLXEXT */
++	GLAMOCardInfo(pScreenPriv);
++
++	GLAMOUnmapReg(pScreenPriv->card, glamoc);
++
++	glamoc->backend_funcs.disable(pScreen);
++}
++
++static void
++GLAMOGetColors(ScreenPtr pScreen, int fb, int n, xColorItem *pdefs)
++{
++	KdScreenPriv(pScreen);
++	GLAMOCardInfo(pScreenPriv);
++
++	glamoc->backend_funcs.getColors(pScreen, fb, n, pdefs);
++}
++
++static void
++GLAMOPutColors(ScreenPtr pScreen, int fb, int n, xColorItem *pdefs)
++{
++	KdScreenPriv(pScreen);
++	GLAMOCardInfo(pScreenPriv);
++
++	glamoc->backend_funcs.putColors(pScreen, fb, n, pdefs);
++}
++
++/* Compute log base 2 of val. */
++int
++GLAMOLog2(int val)
++{
++	int bits;
++
++	for (bits = 0; val != 0; val >>= 1, ++bits)
++		;
++	return bits - 1;
++}
++
++KdCardFuncs GLAMOFuncs = {
++	GLAMOCardInit,		/* cardinit */
++	GLAMOScreenInit,	/* scrinit */
++	GLAMOInitScreen,	/* initScreen */
++	GLAMOFinishInitScreen,	/* finishInitScreen */
++	GLAMOCreateResources,	/* createRes */
++	GLAMOPreserve,		/* preserve */
++	GLAMOEnable,		/* enable */
++	GLAMODPMS,		/* dpms */
++	GLAMODisable,		/* disable */
++	GLAMORestore,		/* restore */
++	GLAMOScreenFini,	/* scrfini */
++	GLAMOCardFini,		/* cardfini */
++
++#if 0
++	GLAMOCursorInit,	/* initCursor */
++	GLAMOCursorEnable,	/* enableCursor */
++	GLAMOCursorDisable,	/* disableCursor */
++	GLAMOCursorFini,	/* finiCursor */
++	GLAMORecolorCursor,	/* recolorCursor */
++#else
++	0,			/* initCursor */
++	0,			/* enableCursor */
++	0,			/* disableCursor */
++	0,			/* finiCursor */
++	0,			/* recolorCursor */
++#endif
++
++
++#if 1
++	GLAMODrawInit,		/* initAccel */
++	GLAMODrawEnable,	/* enableAccel */
++	GLAMODrawDisable,	/* disableAccel */
++	GLAMODrawFini,		/* finiAccel */
++#else
++	0,			/* initAccel */
++	0,			/* enableAccel */
++	0,			/* disableAccel */
++	0,			/* finiAccel */
++#endif
++
++	GLAMOGetColors,		/* getColors */
++	GLAMOPutColors,		/* putColors */
++};
+Index: xserver/hw/kdrive/glamo/glamo.h
+===================================================================
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ xserver/hw/kdrive/glamo/glamo.h	2007-09-26 17:45:48.000000000 +0800
+@@ -0,0 +1,386 @@
++/*
++ * Copyright � 2007 OpenMoko, Inc.
++ *
++ * This driver is based on Xati,
++ * Copyright � 2003 Eric Anholt
++ *
++ * Permission to use, copy, modify, distribute, and sell this software and its
++ * documentation for any purpose is hereby granted without fee, provided that
++ * the above copyright notice appear in all copies and that both that copyright
++ * notice and this permission notice appear in supporting documentation, and
++ * that the name of the copyright holders not be used in advertising or
++ * publicity pertaining to distribution of the software without specific,
++ * written prior permission.  The copyright holders make no representations
++ * about the suitability of this software for any purpose.  It is provided "as
++ * is" without express or implied warranty.
++ *
++ * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
++ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
++ * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
++ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
++ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
++ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
++ * OF THIS SOFTWARE.
++ */
++
++#ifndef _GLAMO_H_
++#define _GLAMO_H_
++
++#ifdef HAVE_CONFIG_H
++#include <kdrive-config.h>
++#endif
++
++#ifdef KDRIVEFBDEV
++#include <fbdev.h>
++#endif
++#ifdef KDRIVEVESA
++#include <vesa.h>
++#endif
++
++#include "kxv.h"
++
++#undef XF86DRI
++#ifdef XF86DRI
++#define USE_DRI
++#include "xf86drm.h"
++#include "dri.h"
++#ifdef GLXEXT
++#include "GL/glxint.h"
++#include "GL/glxtokens.h"
++#include "glamo_dripriv.h"
++#endif
++#endif
++
++#define GLAMO_REG_BASE(c)		((c)->attr.address[0])
++#define GLAMO_REG_SIZE(c)		(0x2400)
++
++#ifdef __powerpc__
++
++static __inline__ void
++MMIO_OUT16(__volatile__ void *base, const unsigned long offset,
++	   const unsigned int val)
++{
++	__asm__ __volatile__(
++			"stwbrx %1,%2,%3\n\t"
++			"eieio"
++			: "=m" (*((volatile unsigned char *)base+offset))
++			: "r" (val), "b" (base), "r" (offset));
++}
++
++static __inline__ CARD32
++MMIO_IN16(__volatile__ void *base, const unsigned long offset)
++{
++	register unsigned int val;
++	__asm__ __volatile__(
++			"lwbrx %0,%1,%2\n\t"
++			"eieio"
++			: "=r" (val)
++			: "b" (base), "r" (offset),
++			"m" (*((volatile unsigned char *)base+offset)));
++	return val;
++}
++
++#else
++
++#define MMIO_OUT16(mmio, a, v)		(*(VOL16 *)((mmio) + (a)) = (v))
++#define MMIO_IN16(mmio, a)		(*(VOL16 *)((mmio) + (a)))
++
++#endif
++
++typedef volatile CARD8	VOL8;
++typedef volatile CARD16	VOL16;
++typedef volatile CARD32	VOL32;
++
++struct backend_funcs {
++	void    (*cardfini)(KdCardInfo *);
++	void    (*scrfini)(KdScreenInfo *);
++	Bool    (*initScreen)(ScreenPtr);
++	Bool    (*finishInitScreen)(ScreenPtr pScreen);
++	Bool	(*createRes)(ScreenPtr);
++	void    (*preserve)(KdCardInfo *);
++	void    (*restore)(KdCardInfo *);
++	Bool    (*dpms)(ScreenPtr, int);
++	Bool    (*enable)(ScreenPtr);
++	void    (*disable)(ScreenPtr);
++	void    (*getColors)(ScreenPtr, int, int, xColorItem *);
++	void    (*putColors)(ScreenPtr, int, int, xColorItem *);
++#ifdef RANDR
++	Bool	(*randrSetConfig) (ScreenPtr, Rotation, int, RRScreenSizePtr);
++#endif
++};
++
++typedef struct _GLAMOCardInfo {
++	union {
++#ifdef KDRIVEFBDEV
++		FbdevPriv fbdev;
++#endif
++#ifdef KDRIVEVESA
++		VesaCardPrivRec vesa;
++#endif
++	} backend_priv;
++	struct backend_funcs backend_funcs;
++
++	char *reg_base;
++	Bool is_3362;
++	CARD32 crtc_pitch;
++	CARD32 crtc2_pitch;
++#ifdef USE_DRI
++	int drmFd;
++#endif /* USE_DRI */
++	Bool use_fbdev, use_vesa;
++} GLAMOCardInfo;
++
++#define getGLAMOCardInfo(kd)	((GLAMOCardInfo *) ((kd)->card->driver))
++#define GLAMOCardInfo(kd)		GLAMOCardInfo *glamoc = getGLAMOCardInfo(kd)
++
++typedef struct _GLAMOCursor {
++	int		width, height;
++	int		xhot, yhot;
++
++	Bool		has_cursor;
++	CursorPtr	pCursor;
++	Pixel		source, mask;
++	KdOffscreenArea *area;
++} GLAMOCursor;
++
++typedef struct _GLAMOPortPriv {
++	int brightness;
++	int saturation;
++	RegionRec clip;
++	CARD32 size;
++	KdOffscreenArea *off_screen;
++	DrawablePtr pDraw;
++	PixmapPtr pPixmap;
++
++	CARD32 src_offset;
++	CARD32 src_pitch;
++	CARD8 *src_addr;
++
++	int id;
++	int src_x1, src_y1, src_x2, src_y2;
++	int dst_x1, dst_y1, dst_x2, dst_y2;
++	int src_w, src_h, dst_w, dst_h;
++} GLAMOPortPrivRec, *GLAMOPortPrivPtr;
++
++typedef struct _dmaBuf {
++	int size;
++	int used;
++	void *address;
++#ifdef USE_DRI
++	drmBufPtr drmBuf;
++#endif
++} dmaBuf;
++
++typedef struct _GLAMOScreenInfo {
++	union {
++#ifdef KDRIVEFBDEV
++		FbdevScrPriv fbdev;
++#endif
++#ifdef KDRIVEVESA
++		VesaScreenPrivRec vesa;
++#endif
++	} backend_priv;
++	KaaScreenInfoRec kaa;
++
++	GLAMOCardInfo *glamoc;
++	KdScreenInfo *screen;
++
++	int		scratch_offset;
++	int		scratch_next;
++	KdOffscreenArea *scratch_area;
++
++	GLAMOCursor	cursor;
++
++	KdVideoAdaptorPtr pAdaptor;
++	int		num_texture_ports;
++
++	Bool		using_dri;	/* If we use the DRM for DMA. */
++
++	KdOffscreenArea *dma_space;	/* For "DMA" from framebuffer. */
++	CARD16		*ring_addr;	/* Beginning of ring buffer. */
++	int		ring_write;	/* Index of write ptr in ring. */
++	int		ring_read;	/* Index of read ptr in ring. */
++	int		ring_len;
++
++	dmaBuf		*indirectBuffer;
++	int		indirectStart;
++
++#ifdef USE_DRI
++	Bool		dma_started;
++
++	drmSize         registerSize;
++	drmHandle       registerHandle;
++	drmHandle       fbHandle;
++
++	drmSize		gartSize;
++	drmHandle	agpMemHandle;		/* Handle from drmAgpAlloc */
++	unsigned long	gartOffset;
++	unsigned char	*AGP;			/* Map */
++	int		agpMode;
++	drmSize         pciSize;
++	drmHandle       pciMemHandle;
++
++	/* ring buffer data */
++	unsigned long	ringStart;		/* Offset into AGP space */
++	drmHandle	ringHandle;		/* Handle from drmAddMap */
++	drmSize		ringMapSize;		/* Size of map */
++	int		ringSize;		/* Size of ring (MB) */
++	unsigned char	*ring;			/* Map */
++
++	unsigned long	ringReadOffset;		/* Offset into AGP space */
++	drmHandle	ringReadPtrHandle;	/* Handle from drmAddMap */
++	drmSize		ringReadMapSize;	/* Size of map */
++	unsigned char	*ringReadPtr;		/* Map */
++
++	/* vertex/indirect buffer data */
++	unsigned long	bufStart;		/* Offset into AGP space */
++	drmHandle	bufHandle;		/* Handle from drmAddMap */
++	drmSize		bufMapSize;		/* Size of map */
++	int		bufSize;		/* Size of buffers (MB) */
++	unsigned char	*buf;			/* Map */
++	int		bufNumBufs;		/* Number of buffers */
++	drmBufMapPtr	buffers;		/* Buffer map */
++
++	/* AGP Texture data */
++	unsigned long	gartTexStart;		/* Offset into AGP space */
++	drmHandle	gartTexHandle;		/* Handle from drmAddMap */
++	drmSize		gartTexMapSize;		/* Size of map */
++	int		gartTexSize;		/* Size of AGP tex space (MB) */
++	unsigned char	*gartTex;		/* Map */
++	int		log2GARTTexGran;
++
++	int		DMAusecTimeout;   /* CCE timeout in usecs */
++
++	/* DRI screen private data */
++	int		frontOffset;
++	int		frontPitch;
++	int		backOffset;
++	int		backPitch;
++	int		depthOffset;
++	int		depthPitch;
++	int		spanOffset;
++	int		textureOffset;
++	int		textureSize;
++	int		log2TexGran;
++
++	int		irqEnabled;
++
++	int		serverContext;
++
++	DRIInfoPtr	pDRIInfo;
++#ifdef GLXEXT
++	int		numVisualConfigs;
++	__GLXvisualConfig *pVisualConfigs;
++	GLAMOConfigPrivPtr pVisualConfigsPriv;
++#endif /* GLXEXT */
++#endif /* USE_DRI */
++} GLAMOScreenInfo;
++
++#define getGLAMOScreenInfo(kd)	((GLAMOScreenInfo *) ((kd)->screen->driver))
++#define GLAMOScreenInfo(kd)	GLAMOScreenInfo *glamos = getGLAMOScreenInfo(kd)
++
++typedef union { float f; CARD32 i; } fi_type;
++
++/* Surely there's a better way to go about this */
++static inline CARD32
++GLAMOFloatAsInt(float val)
++{
++	fi_type fi;
++
++	fi.f = val;
++	return fi.i;
++}
++
++#define GET_FLOAT_BITS(x) GLAMOFloatAsInt(x)
++
++static inline void
++MMIOSetBitMask(char *mmio, CARD32 reg, CARD16 mask, CARD16 val)
++{
++	CARD16 tmp;
++
++	val &= mask;
++
++	tmp = MMIO_IN16(mmio, reg);
++	tmp &= ~mask;
++	tmp |= val;
++
++	MMIO_OUT16(mmio, reg, tmp);
++}
++
++/* glamo.c */
++Bool
++GLAMOMapReg(KdCardInfo *card, GLAMOCardInfo *glamoc);
++
++void
++GLAMOUnmapReg(KdCardInfo *card, GLAMOCardInfo *glamoc);
++
++/* glamo_draw.c */
++void
++GLAMODrawSetup(ScreenPtr pScreen);
++
++Bool
++GLAMODrawInit(ScreenPtr pScreen);
++
++void
++GLAMODrawEnable(ScreenPtr pScreen);
++
++void
++GLAMODrawDisable(ScreenPtr pScreen);
++
++void
++GLAMODrawFini(ScreenPtr pScreen);
++
++/* glamo_dri.c */
++#ifdef USE_DRI
++Bool
++GLAMODRIScreenInit(ScreenPtr pScreen);
++
++void
++GLAMODRICloseScreen(ScreenPtr pScreen);
++
++void
++GLAMODRIDMAStart(GLAMOScreenInfo *glamos);
++
++void
++GLAMODRIDMAStop(GLAMOScreenInfo *glamos);
++
++void
++GLAMODRIDMAReset(GLAMOScreenInfo *glamos);
++
++void
++GLAMODRIDispatchIndirect(GLAMOScreenInfo *glamos, Bool discard);
++
++drmBufPtr
++GLAMODRIGetBuffer(GLAMOScreenInfo *glamos);
++
++#endif /* USE_DRI */
++
++/* glamo_cursor.c */
++Bool
++GLAMOCursorInit(ScreenPtr pScreen);
++
++void
++GLAMOCursorEnable(ScreenPtr pScreen);
++
++void
++GLAMOCursorDisable(ScreenPtr pScreen);
++
++void
++GLAMOCursorFini(ScreenPtr pScreen);
++
++void
++GLAMORecolorCursor(ScreenPtr pScreen, int ndef, xColorItem *pdef);
++
++int
++GLAMOLog2(int val);
++
++/* glamo_video.c */
++Bool
++GLAMOInitVideo(ScreenPtr pScreen);
++
++void
++GLAMOFiniVideo(ScreenPtr pScreen);
++
++extern KdCardFuncs GLAMOFuncs;
++
++#endif /* _GLAMO_H_ */
+Index: xserver/hw/kdrive/glamo/glamo_dma.c
+===================================================================
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ xserver/hw/kdrive/glamo/glamo_dma.c	2007-09-26 17:45:16.000000000 +0800
+@@ -0,0 +1,410 @@
++/*
++ * Copyright � 2007 OpenMoko, Inc.
++ *
++ * This driver is based on Xati,
++ * Copyright � 2004 Eric Anholt
++ *
++ * Permission to use, copy, modify, distribute, and sell this software and its
++ * documentation for any purpose is hereby granted without fee, provided that
++ * the above copyright notice appear in all copies and that both that copyright
++ * notice and this permission notice appear in supporting documentation, and
++ * that the name of the copyright holders not be used in advertising or
++ * publicity pertaining to distribution of the software without specific,
++ * written prior permission.  The copyright holders make no representations
++ * about the suitability of this software for any purpose.  It is provided "as
++ * is" without express or implied warranty.
++ *
++ * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
++ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
++ * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
++ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
++ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
++ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
++ * OF THIS SOFTWARE.
++ */
++
++#include <sys/time.h>
++
++#include "glamo.h"
++#include "glamo-regs.h"
++#include "glamo_dma.h"
++#include "glamo_draw.h"
++
++#ifdef USE_DRI
++#include "radeon_common.h"
++#include "glamo_sarea.h"
++#endif /* USE_DRI */
++
++#define DEBUG_FIFO 1
++
++#if DEBUG_FIFO
++static void
++GLAMODebugFifo(GLAMOScreenInfo *glamos)
++{
++	GLAMOCardInfo *glamoc = glamos->glamoc;
++	char *mmio = glamoc->reg_base;
++	CARD32 offset;
++
++	ErrorF("GLAMO_REG_CQ_STATUS: 0x%04x\n",
++	    MMIO_IN16(mmio, GLAMO_REG_CQ_STATUS));
++
++	offset = MMIO_IN16(mmio, GLAMO_REG_CQ_WRITE_ADDRL);
++	offset |= (MMIO_IN16(mmio, GLAMO_REG_CQ_WRITE_ADDRH) << 16) & 0x7;
++	ErrorF("GLAMO_REG_CQ_WRITE_ADDR: 0x%08x\n", (unsigned int) offset);
++
++	offset = MMIO_IN16(mmio, GLAMO_REG_CQ_READ_ADDRL);
++	offset |= (MMIO_IN16(mmio, GLAMO_REG_CQ_READ_ADDRH) << 16) & 0x7;
++	ErrorF("GLAMO_REG_CQ_READ_ADDR: 0x%08x\n", (unsigned int) offset);
++}
++#endif
++
++void
++GLAMOEngineReset(ScreenPtr pScreen, enum glamo_engine engine)
++{
++	KdScreenPriv(pScreen);
++	GLAMOCardInfo(pScreenPriv);
++	CARD32 reg;
++	CARD16 mask;
++	char *mmio = glamoc->reg_base;
++
++	if (!mmio)
++		return;
++
++	switch (engine) {
++	case GLAMO_ENGINE_ISP:
++		reg = GLAMO_REG_CLOCK_ISP;
++		mask = GLAMO_CLOCK_ISP2_RESET;
++		break;
++	case GLAMO_ENGINE_CQ:
++		reg = GLAMO_REG_CLOCK_2D;
++		mask = GLAMO_CLOCK_2D_CQ_RESET;
++		break;
++	case GLAMO_ENGINE_2D:
++		reg = GLAMO_REG_CLOCK_2D;
++		mask = GLAMO_CLOCK_2D_RESET;
++		break;
++	}
++
++	MMIOSetBitMask(mmio, reg, mask, 0xffff);
++	usleep(1000);
++	MMIOSetBitMask(mmio, reg, mask, 0);
++	usleep(1000);
++}
++
++void
++GLAMOEngineDisable(ScreenPtr pScreen, enum glamo_engine engine)
++{
++	KdScreenPriv(pScreen);
++	GLAMOCardInfo(pScreenPriv);
++	char *mmio = glamoc->reg_base;
++
++	if (!mmio)
++		return;
++
++	return;
++}
++
++void
++GLAMOEngineEnable(ScreenPtr pScreen, enum glamo_engine engine)
++{
++	KdScreenPriv(pScreen);
++	GLAMOCardInfo(pScreenPriv);
++	char *mmio = glamoc->reg_base;
++
++	if (!mmio)
++		return;
++
++	switch (engine) {
++	case GLAMO_ENGINE_ISP:
++		MMIOSetBitMask(mmio, GLAMO_REG_CLOCK_ISP,
++			       GLAMO_CLOCK_ISP_EN_M2CLK |
++			       GLAMO_CLOCK_ISP_EN_I1CLK,
++			       0xffff);
++		MMIOSetBitMask(mmio, GLAMO_REG_CLOCK_GEN5_2,
++			       GLAMO_CLOCK_GEN52_EN_DIV_ICLK,
++			       0xffff);
++		MMIOSetBitMask(mmio, GLAMO_REG_CLOCK_GEN5_1,
++			       GLAMO_CLOCK_GEN51_EN_DIV_JCLK,
++			       0xffff);
++		MMIOSetBitMask(mmio, GLAMO_REG_HOSTBUS(2),
++			       GLAMO_HOSTBUS2_MMIO_EN_ISP,
++			       0xffff);
++		break;
++	case GLAMO_ENGINE_CQ:
++		MMIOSetBitMask(mmio, GLAMO_REG_CLOCK_2D,
++			       GLAMO_CLOCK_2D_EN_M6CLK,
++			       0xffff);
++		MMIOSetBitMask(mmio, GLAMO_REG_HOSTBUS(2),
++			       GLAMO_HOSTBUS2_MMIO_EN_CQ,
++			       0xffff);
++		MMIOSetBitMask(mmio, GLAMO_REG_CLOCK_GEN5_1,
++			       GLAMO_CLOCK_GEN51_EN_DIV_MCLK,
++			       0xffff);
++		break;
++	case GLAMO_ENGINE_2D:
++		MMIOSetBitMask(mmio, GLAMO_REG_CLOCK_2D,
++				GLAMO_CLOCK_2D_EN_M7CLK |
++				GLAMO_CLOCK_2D_EN_GCLK |
++				GLAMO_CLOCK_2D_DG_M7CLK |
++				GLAMO_CLOCK_2D_DG_GCLK,
++				0xffff);
++		MMIOSetBitMask(mmio, GLAMO_REG_HOSTBUS(2),
++			       GLAMO_HOSTBUS2_MMIO_EN_2D,
++			       0xffff);
++		MMIOSetBitMask(mmio, GLAMO_REG_CLOCK_GEN5_1,
++			       GLAMO_CLOCK_GEN51_EN_DIV_GCLK,
++			       0xffff);
++		break;
++	}
++}
++
++void
++GLAMOWaitIdle(GLAMOScreenInfo *glamos)
++{
++	GLAMOCardInfo *glamoc = glamos->glamoc;
++	char *mmio = glamoc->reg_base;
++	CARD16 status;
++	TIMEOUT_LOCALS;
++
++	if (glamos->indirectBuffer != NULL)
++		GLAMOFlushIndirect(glamos, 0);
++
++#ifdef USE_DRI
++	if (glamos->using_dri) {
++		int ret = 0;
++		int cmd = (glamoc->is_3362 ? DRM_RADEON_CP_IDLE :
++		    DRM_R128_CCE_IDLE);
++		WHILE_NOT_TIMEOUT(2) {
++			ret = drmCommandNone(glamoc->drmFd, cmd);
++			if (ret != -EBUSY)
++				break;
++		}
++		if (TIMEDOUT()) {
++			GLAMODebugFifo(glamos);
++			FatalError("Timed out idling CCE (card hung)\n");
++		}
++		if (ret != 0)
++			ErrorF("Failed to idle DMA, returned %d\n", ret);
++		return;
++	}
++#endif
++
++	WHILE_NOT_TIMEOUT(.5) {
++		status = MMIO_IN16(mmio, GLAMO_REG_CQ_STATUS);
++		if ((status & (1 << 2)) && !(status & (1 << 8)))
++			break;
++	}
++	if (TIMEDOUT()) {
++		ErrorF("Timeout idling accelerator, resetting...\n");
++		GLAMOEngineReset(glamos->screen->pScreen, GLAMO_ENGINE_CQ);
++		GLAMODrawSetup(glamos->screen->pScreen);
++	}
++
++#if DEBUG_FIFO
++	ErrorF("Idle?\n");
++	GLAMODebugFifo(glamos);
++#endif
++}
++
++dmaBuf *
++GLAMOGetDMABuffer(GLAMOScreenInfo *glamos)
++{
++	dmaBuf *buf;
++
++	buf = (dmaBuf *)xalloc(sizeof(dmaBuf));
++	if (buf == NULL)
++		return NULL;
++
++#ifdef USE_DRI
++	if (glamos->using_dri) {
++		buf->drmBuf = GLAMODRIGetBuffer(glamos);
++		if (buf->drmBuf == NULL) {
++			xfree(buf);
++			return NULL;
++		}
++		buf->size = buf->drmBuf->total;
++		buf->used = buf->drmBuf->used;
++		buf->address = buf->drmBuf->address;
++		return buf;
++	}
++#endif /* USE_DRI */
++
++	buf->size = glamos->ring_len / 2;
++	buf->address = xalloc(buf->size);
++	if (buf->address == NULL) {
++		xfree(buf);
++		return NULL;
++	}
++	buf->used = 0;
++
++	return buf;
++}
++
++static void
++GLAMODispatchIndirectDMA(GLAMOScreenInfo *glamos)
++{
++	GLAMOCardInfo *glamoc = glamos->glamoc;
++	dmaBuf *buf = glamos->indirectBuffer;
++	char *mmio = glamoc->reg_base;
++	CARD16 *addr;
++	int count, ring_count;
++	TIMEOUT_LOCALS;
++
++	addr = (CARD16 *)((char *)buf->address + glamos->indirectStart);
++	count = (buf->used - glamos->indirectStart) / 2;
++	ring_count = glamos->ring_len / 2;
++
++	WHILE_NOT_TIMEOUT(.5) {
++		if (count <= 0)
++			break;
++
++		glamos->ring_addr[glamos->ring_write++] = *addr++;
++		if (glamos->ring_write >= ring_count)
++			glamos->ring_write = 0;
++
++		while (glamos->ring_write == glamos->ring_read)
++		{
++			glamos->ring_read =
++				MMIO_IN16(mmio, GLAMO_REG_CQ_READ_ADDRL);
++			glamos->ring_read |=
++				(MMIO_IN16(mmio, GLAMO_REG_CQ_READ_ADDRH) & 0x7) << 16;
++		}
++
++		count--;
++	}
++	if (TIMEDOUT()) {
++		ErrorF("Timeout submitting packets, resetting...\n");
++		GLAMOEngineReset(glamos->screen->pScreen, GLAMO_ENGINE_CQ);
++		GLAMODrawSetup(glamos->screen->pScreen);
++	}
++
++	MMIO_OUT16(mmio, GLAMO_REG_CQ_WRITE_ADDRH,
++			 (glamos->ring_write >> 15) & 0x7);
++	MMIO_OUT16(mmio, GLAMO_REG_CQ_WRITE_ADDRL,
++			 (glamos->ring_write <<  1) & 0xffff);
++}
++
++void
++GLAMOFlushIndirect(GLAMOScreenInfo *glamos, Bool discard)
++{
++	dmaBuf *buf = glamos->indirectBuffer;
++
++	if ((glamos->indirectStart == buf->used) && !discard)
++		return;
++
++#if DEBUG_FIFO
++	ErrorF("Dispatching %d DWORDS\n", (buf->used - glamos->indirectStart) /
++	    4);
++#endif
++
++#ifdef USE_DRI
++	if (glamos->using_dri) {
++		buf->drmBuf->used = buf->used;
++		GLAMODRIDispatchIndirect(glamos, discard);
++		if (discard) {
++			buf->drmBuf = GLAMODRIGetBuffer(glamos);
++			buf->size = buf->drmBuf->total;
++			buf->used = buf->drmBuf->used;
++			buf->address = buf->drmBuf->address;
++			glamos->indirectStart = 0;
++		} else {
++			/* Start on a double word boundary */
++			glamos->indirectStart = buf->used = (buf->used + 7) & ~7;
++		}
++		return;
++	}
++#endif /* USE_DRI */
++
++	GLAMODispatchIndirectDMA(glamos);
++
++	buf->used = 0;
++	glamos->indirectStart = 0;
++}
++
++static Bool
++GLAMODMAInit(ScreenPtr pScreen)
++{
++	KdScreenPriv(pScreen);
++	GLAMOScreenInfo(pScreenPriv);
++	GLAMOCardInfo(pScreenPriv);
++	char *mmio = glamoc->reg_base;
++	int cq_len = 63;
++
++	glamos->ring_len = (cq_len + 1) * 1024;
++
++	glamos->dma_space = KdOffscreenAlloc(pScreen, glamos->ring_len + 4,
++			                     16, TRUE, NULL, NULL);
++	if (!glamos->dma_space)
++		return FALSE;
++
++	glamos->ring_addr = (CARD16 *) (pScreenPriv->screen->memory_base +
++			                glamos->dma_space->offset);
++	glamos->ring_read = 0;
++	glamos->ring_write = 0;
++
++	/* make the decoder happy? */
++	glamos->ring_addr[glamos->ring_len / 2] = 0x0;
++	glamos->ring_addr[glamos->ring_len / 2 + 1] = 0x0;
++
++	GLAMOEngineEnable(glamos->screen->pScreen, GLAMO_ENGINE_CQ);
++	GLAMOEngineReset(glamos->screen->pScreen, GLAMO_ENGINE_CQ);
++
++	MMIO_OUT16(mmio, GLAMO_REG_CQ_BASE_ADDRL,
++			 glamos->dma_space->offset & 0xffff);
++	MMIO_OUT16(mmio, GLAMO_REG_CQ_BASE_ADDRH,
++			 (glamos->dma_space->offset >> 16) & 0x7f);
++	MMIO_OUT16(mmio, GLAMO_REG_CQ_LEN, cq_len);
++
++	MMIO_OUT16(mmio, GLAMO_REG_CQ_WRITE_ADDRH, 0);
++	MMIO_OUT16(mmio, GLAMO_REG_CQ_WRITE_ADDRL, 0);
++	MMIO_OUT16(mmio, GLAMO_REG_CQ_READ_ADDRH, 0);
++	MMIO_OUT16(mmio, GLAMO_REG_CQ_READ_ADDRL, 0);
++	MMIO_OUT16(mmio, GLAMO_REG_CQ_CONTROL,
++			 1 << 12 |
++			 5 << 8 |
++			 8 << 4);
++
++	return TRUE;
++}
++
++void
++GLAMODMASetup(ScreenPtr pScreen)
++{
++	KdScreenPriv(pScreen);
++	GLAMOScreenInfo(pScreenPriv);
++
++#ifdef USE_DRI
++	if (glamos->using_dri)
++		GLAMODRIDMAStart(glamos);
++#endif /* USE_DRI */
++
++	if (!glamos->using_dri)
++		GLAMODMAInit(pScreen);
++
++	glamos->indirectBuffer = GLAMOGetDMABuffer(glamos);
++	if (glamos->indirectBuffer == FALSE)
++		FatalError("Failed to allocate DMA buffer.\n");
++
++	if (glamos->using_dri)
++		ErrorF("Initialized DRI DMA\n");
++	else
++		ErrorF("Initialized DMA\n");
++}
++
++void
++GLAMODMATeardown(ScreenPtr pScreen)
++{
++	KdScreenPriv(pScreen);
++	GLAMOScreenInfo(pScreenPriv);
++
++	GLAMOWaitIdle(glamos);
++
++#ifdef USE_DRI
++	if (glamos->using_dri)
++		GLAMODRIDMAStop(glamos);
++#endif /* USE_DRI */
++
++	xfree(glamos->indirectBuffer->address);
++	xfree(glamos->indirectBuffer);
++	glamos->indirectBuffer = NULL;
++}
+Index: xserver/hw/kdrive/glamo/glamo_dma.h
+===================================================================
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ xserver/hw/kdrive/glamo/glamo_dma.h	2007-09-25 19:17:53.000000000 +0800
+@@ -0,0 +1,159 @@
++/*
++ * Copyright � 2007 OpenMoko, Inc.
++ *
++ * This driver is based on Xati,
++ * Copyright � 2004 Eric Anholt
++ *
++ * Permission to use, copy, modify, distribute, and sell this software and its
++ * documentation for any purpose is hereby granted without fee, provided that
++ * the above copyright notice appear in all copies and that both that copyright
++ * notice and this permission notice appear in supporting documentation, and
++ * that the name of the copyright holders not be used in advertising or
++ * publicity pertaining to distribution of the software without specific,
++ * written prior permission.  The copyright holders make no representations
++ * about the suitability of this software for any purpose.  It is provided "as
++ * is" without express or implied warranty.
++ *
++ * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
++ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
++ * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
++ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
++ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
++ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
++ * OF THIS SOFTWARE.
++ */
++
++#ifndef _GLAMO_DMA_H_
++#define _GLAMO_DMA_H_
++
++#define CCE_DEBUG 1
++
++#if !CCE_DEBUG
++#define DMA_PACKET0(reg, count)						\
++	(reg)
++#else
++#define DMA_PACKET0(reg, count)						\
++	(__packet0count = (count), __reg = (reg),			\
++	(reg))
++#endif
++#define DMA_PACKET1(reg1, reg2)						\
++	(GLAMO_CCE_PACKET1 |						\
++	(((reg2) >> 2) << GLAMO_CCE_PACKET1_REG_2_SHIFT) |  ((reg1) >> 2))
++#define DMA_PACKET3(type, count)					\
++	((type) | (((count) - 1) << 16))
++
++#if !CCE_DEBUG
++
++#define RING_LOCALS	CARD16 *__head; int __count
++#define BEGIN_DMA(n)							\
++do {									\
++	if ((glamos->indirectBuffer->used + 2 * (n)) >			\
++	    glamos->indirectBuffer->size) {				\
++		GLAMOFlushIndirect(glamos, 1);				\
++	}								\
++	__head = (CARD16 *)((char *)glamos->indirectBuffer->address +	\
++	    glamos->indirectBuffer->used);				\
++	__count = 0;							\
++} while (0)
++#define END_DMA() do {							\
++	glamos->indirectBuffer->used += __count * 2;			\
++} while (0)
++
++#else
++
++#define RING_LOCALS	\
++	CARD16 *__head; int __count, __total, __reg, __packet0count
++#define BEGIN_DMA(n)							\
++do {									\
++	if ((glamos->indirectBuffer->used + 2 * (n)) >			\
++	    glamos->indirectBuffer->size) {				\
++		GLAMOFlushIndirect(glamos, 1);				\
++	}								\
++	__head = (CARD16 *)((char *)glamos->indirectBuffer->address +	\
++	    glamos->indirectBuffer->used);				\
++	__count = 0;							\
++	__total = n;							\
++	__reg = 0;								\
++	__packet0count = 0;								\
++} while (0)
++#define END_DMA() do {							\
++	if (__count != __total)						\
++		FatalError("count != total (%d vs %d) at %s:%d\n",	 \
++		     __count, __total, __FILE__, __LINE__);		\
++	glamos->indirectBuffer->used += __count * 2;			\
++} while (0)
++
++#endif
++
++#define OUT_RING(val) do {						\
++	__head[__count++] = (val);					\
++} while (0)
++
++#define OUT_RING_REG(reg, val) do {					\
++	if (__reg != reg)						\
++		FatalError("unexpected reg (0x%x vs 0x%x) at %s:%d\n",	\
++		    reg, __reg, __FILE__, __LINE__);			\
++	if (__packet0count-- <= 0)					\
++		FatalError("overrun of packet0 at %s:%d\n",		\
++		    __FILE__, __LINE__);				\
++	__head[__count++] = (val);					\
++	__reg += 4;							\
++} while (0)
++
++#define OUT_RING_F(x) OUT_RING(GET_FLOAT_BITS(x))
++
++#define OUT_REG(reg, val)						\
++do {									\
++	OUT_RING(DMA_PACKET0(reg, 1));					\
++	OUT_RING(val);							\
++} while (0)
++
++#define TIMEOUT_LOCALS struct timeval _target, _curtime
++
++static inline Bool
++tv_le(struct timeval *tv1, struct timeval *tv2)
++{
++	if (tv1->tv_sec < tv2->tv_sec ||
++	    (tv1->tv_sec == tv2->tv_sec && tv1->tv_usec < tv2->tv_usec))
++		return TRUE;
++	else
++		return FALSE;
++}
++
++#define WHILE_NOT_TIMEOUT(_timeout)					\
++	gettimeofday(&_target, NULL);					\
++	_target.tv_usec += ((_timeout) * 1000000);			\
++	_target.tv_sec += _target.tv_usec / 1000000;			\
++	_target.tv_usec = _target.tv_usec % 1000000;			\
++	while (gettimeofday(&_curtime, NULL), tv_le(&_curtime, &_target))
++
++#define TIMEDOUT()	(!tv_le(&_curtime, &_target))
++
++dmaBuf *
++GLAMOGetDMABuffer(GLAMOScreenInfo *glamos);
++
++void
++GLAMOFlushIndirect(GLAMOScreenInfo *glamos, Bool discard);
++
++void
++GLAMODMASetup(ScreenPtr pScreen);
++
++void
++GLAMODMATeardown(ScreenPtr pScreen);
++
++enum glamo_engine {
++	GLAMO_ENGINE_ISP,
++	GLAMO_ENGINE_CQ,
++	GLAMO_ENGINE_2D,
++};
++
++void
++GLAMOEngineEnable(ScreenPtr pScreen, enum glamo_engine engine);
++
++void
++GLAMOEngineDisable(ScreenPtr pScreen, enum glamo_engine engine);
++
++void
++GLAMOEngineReset(ScreenPtr pScreen, enum glamo_engine engine);
++
++#endif /* _GLAMO_DMA_H_ */
+Index: xserver/hw/kdrive/glamo/glamo_draw.c
+===================================================================
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ xserver/hw/kdrive/glamo/glamo_draw.c	2007-09-26 17:46:30.000000000 +0800
+@@ -0,0 +1,522 @@
++/*
++ * Copyright � 2007 OpenMoko, Inc.
++ *
++ * This driver is based on Xati,
++ * Copyright � 2003 Eric Anholt
++ *
++ * Permission to use, copy, modify, distribute, and sell this software and its
++ * documentation for any purpose is hereby granted without fee, provided that
++ * the above copyright notice appear in all copies and that both that copyright
++ * notice and this permission notice appear in supporting documentation, and
++ * that the name of the copyright holders not be used in advertising or
++ * publicity pertaining to distribution of the software without specific,
++ * written prior permission.  The copyright holders make no representations
++ * about the suitability of this software for any purpose.  It is provided "as
++ * is" without express or implied warranty.
++ *
++ * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
++ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
++ * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
++ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
++ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
++ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
++ * OF THIS SOFTWARE.
++ */
++
++#ifdef HAVE_CONFIG_H
++#include <kdrive-config.h>
++#endif
++#include "glamo.h"
++#include "glamo-regs.h"
++#include "glamo_dma.h"
++#include "glamo_draw.h"
++#include "kaa.h"
++
++static const CARD8 GLAMOSolidRop[16] = {
++    /* GXclear      */      0x00,         /* 0 */
++    /* GXand        */      0xa0,         /* src AND dst */
++    /* GXandReverse */      0x50,         /* src AND NOT dst */
++    /* GXcopy       */      0xf0,         /* src */
++    /* GXandInverted*/      0x0a,         /* NOT src AND dst */
++    /* GXnoop       */      0xaa,         /* dst */
++    /* GXxor        */      0x5a,         /* src XOR dst */
++    /* GXor         */      0xfa,         /* src OR dst */
++    /* GXnor        */      0x05,         /* NOT src AND NOT dst */
++    /* GXequiv      */      0xa5,         /* NOT src XOR dst */
++    /* GXinvert     */      0x55,         /* NOT dst */
++    /* GXorReverse  */      0xf5,         /* src OR NOT dst */
++    /* GXcopyInverted*/     0x0f,         /* NOT src */
++    /* GXorInverted */      0xaf,         /* NOT src OR dst */
++    /* GXnand       */      0x5f,         /* NOT src OR NOT dst */
++    /* GXset        */      0xff,         /* 1 */
++};
++
++static const CARD8 GLAMOBltRop[16] = {
++    /* GXclear      */      0x00,         /* 0 */
++    /* GXand        */      0x88,         /* src AND dst */
++    /* GXandReverse */      0x44,         /* src AND NOT dst */
++    /* GXcopy       */      0xcc,         /* src */
++    /* GXandInverted*/      0x22,         /* NOT src AND dst */
++    /* GXnoop       */      0xaa,         /* dst */
++    /* GXxor        */      0x66,         /* src XOR dst */
++    /* GXor         */      0xee,         /* src OR dst */
++    /* GXnor        */      0x11,         /* NOT src AND NOT dst */
++    /* GXequiv      */      0x99,         /* NOT src XOR dst */
++    /* GXinvert     */      0x55,         /* NOT dst */
++    /* GXorReverse  */      0xdd,         /* src OR NOT dst */
++    /* GXcopyInverted*/     0x33,         /* NOT src */
++    /* GXorInverted */      0xbb,         /* NOT src OR dst */
++    /* GXnand       */      0x77,         /* NOT src OR NOT dst */
++    /* GXset        */      0xff,         /* 1 */
++};
++
++GLAMOScreenInfo *accel_glamos;
++CARD32 settings, color, src_pitch_offset, dst_pitch_offset;
++
++int sample_count;
++float sample_offsets_x[255];
++float sample_offsets_y[255];
++
++void
++GLAMODrawSetup(ScreenPtr pScreen)
++{
++	GLAMOEngineEnable(pScreen, GLAMO_ENGINE_2D);
++	GLAMOEngineReset(pScreen, GLAMO_ENGINE_2D);
++}
++
++static void
++GLAMOWaitMarker(ScreenPtr pScreen, int marker)
++{
++	KdScreenPriv(pScreen);
++	GLAMOScreenInfo(pScreenPriv);
++
++	ENTER_DRAW(0);
++	GLAMOWaitIdle(glamos);
++	LEAVE_DRAW(0);
++}
++
++#if GLAMO_TRACE_DRAW
++void
++GLAMOEnterDraw (PixmapPtr pPix, const char *function)
++{
++    if (pPix != NULL) {
++	KdScreenPriv(pPix->drawable.pScreen);
++	CARD32 offset;
++
++	offset = ((CARD8 *)pPix->devPrivate.ptr -
++		  pScreenPriv->screen->memory_base);
++
++	ErrorF ("Enter %s 0x%x (%dx%dx%d/%d)\n", function, (unsigned int) offset,
++	    pPix->drawable.width, pPix->drawable.height, pPix->drawable.depth,
++	    (unsigned int) pPix->drawable.bitsPerPixel);
++    } else
++	ErrorF ("Enter %s\n", function);
++}
++
++void
++GLAMOLeaveDraw (PixmapPtr pPix, const char *function)
++{
++    if (pPix != NULL) {
++	KdScreenPriv(pPix->drawable.pScreen);
++	CARD32 offset;
++
++	offset = ((CARD8 *)pPix->devPrivate.ptr -
++		  pScreenPriv->screen->memory_base);
++
++	ErrorF ("Leave %s 0x%x\n", function, (unsigned int) offset);
++    } else
++	ErrorF ("Leave %s\n", function);
++}
++#endif
++
++static Bool
++GLAMOPrepareSolid(PixmapPtr pPix, int alu, Pixel pm, Pixel fg)
++{
++	KdScreenPriv(pPix->drawable.pScreen);
++	GLAMOScreenInfo(pScreenPriv);
++	CARD32 offset, pitch;
++	FbBits mask;
++	RING_LOCALS;
++
++	if (pPix->drawable.bitsPerPixel != 16)
++		GLAMO_FALLBACK(("Only 16bpp is supported\n"));
++
++	mask = FbFullMask(16);
++	if ((pm & mask) != mask)
++		GLAMO_FALLBACK(("Can't do planemask 0x%08x\n", (unsigned int) pm));
++
++	accel_glamos = glamos;
++
++	settings = GLAMOSolidRop[alu] << 8;
++	offset = ((CARD8 *) pPix->devPrivate.ptr -
++			pScreenPriv->screen->memory_base);
++	pitch = pPix->devKind;
++
++	ENTER_DRAW(pPix);
++
++	BEGIN_DMA(12);
++	OUT_REG(GLAMO_REG_2D_DST_ADDRL, offset & 0xffff);
++	OUT_REG(GLAMO_REG_2D_DST_ADDRH, (offset >> 16) & 0x7f);
++	OUT_REG(GLAMO_REG_2D_DST_PITCH, pitch);
++	OUT_REG(GLAMO_REG_2D_DST_HEIGHT, pPix->drawable.height);
++	OUT_REG(GLAMO_REG_2D_PAT_FG, fg);
++	OUT_REG(GLAMO_REG_2D_COMMAND2, settings);
++	END_DMA();
++
++	LEAVE_DRAW(pPix);
++
++	return TRUE;
++}
++
++static void
++GLAMOSolid(int x1, int y1, int x2, int y2)
++{
++	ENTER_DRAW(0);
++	GLAMOScreenInfo *glamos = accel_glamos;
++	RING_LOCALS;
++
++	BEGIN_DMA(14);
++	OUT_REG(GLAMO_REG_2D_DST_X, x1);
++	OUT_REG(GLAMO_REG_2D_DST_Y, y1);
++	OUT_REG(GLAMO_REG_2D_RECT_WIDTH, x2 - x1);
++	OUT_REG(GLAMO_REG_2D_RECT_HEIGHT, y2 - y1);
++	OUT_REG(GLAMO_REG_2D_COMMAND3, 0);
++	OUT_REG(GLAMO_REG_2D_ID1, 0);
++	OUT_REG(GLAMO_REG_2D_ID2, 0);
++	END_DMA();
++	LEAVE_DRAW(0);
++}
++
++static void
++GLAMODoneSolid(void)
++{
++	ENTER_DRAW(0);
++	LEAVE_DRAW(0);
++}
++
++static Bool
++GLAMOPrepareCopy(PixmapPtr pSrc, PixmapPtr pDst, int dx, int dy, int alu, Pixel pm)
++{
++	KdScreenPriv(pDst->drawable.pScreen);
++	GLAMOScreenInfo(pScreenPriv);
++	CARD32 src_offset, src_pitch;
++	CARD32 dst_offset, dst_pitch;
++	FbBits mask;
++	RING_LOCALS;
++
++	if (pSrc->drawable.bitsPerPixel != 16 ||
++	    pDst->drawable.bitsPerPixel != 16)
++		GLAMO_FALLBACK(("Only 16bpp is supported"));
++
++	mask = FbFullMask(16);
++	if ((pm & mask) != mask)
++		GLAMO_FALLBACK(("Can't do planemask 0x%08x", (unsigned int) pm));
++
++	accel_glamos = glamos;
++
++	src_offset = ((CARD8 *) pSrc->devPrivate.ptr -
++			pScreenPriv->screen->memory_base);
++	src_pitch = pSrc->devKind;
++
++	dst_offset = ((CARD8 *) pDst->devPrivate.ptr -
++			pScreenPriv->screen->memory_base);
++	dst_pitch = pDst->devKind;
++
++	settings = GLAMOBltRop[alu] << 8;
++
++	ENTER_DRAW (pDst);
++
++	BEGIN_DMA(16);
++
++	OUT_REG(GLAMO_REG_2D_SRC_ADDRL, src_offset & 0xffff);
++	OUT_REG(GLAMO_REG_2D_SRC_ADDRH, (src_offset >> 16) & 0x7f);
++	OUT_REG(GLAMO_REG_2D_SRC_PITCH, src_pitch);
++
++	OUT_REG(GLAMO_REG_2D_DST_ADDRL, dst_offset & 0xffff);
++	OUT_REG(GLAMO_REG_2D_DST_ADDRH, (dst_offset >> 16) & 0x7f);
++	OUT_REG(GLAMO_REG_2D_DST_PITCH, dst_pitch);
++	OUT_REG(GLAMO_REG_2D_DST_HEIGHT, pDst->drawable.height);
++
++	OUT_REG(GLAMO_REG_2D_COMMAND2, settings);
++
++	END_DMA();
++
++	LEAVE_DRAW(pDst);
++
++	return TRUE;
++}
++
++static void
++GLAMOCopy(int srcX, int srcY, int dstX, int dstY, int w, int h)
++{
++	GLAMOScreenInfo *glamos = accel_glamos;
++	RING_LOCALS;
++
++	BEGIN_DMA(18);
++	OUT_REG(GLAMO_REG_2D_SRC_X, srcX);
++	OUT_REG(GLAMO_REG_2D_SRC_Y, srcY);
++	OUT_REG(GLAMO_REG_2D_DST_X, dstX);
++	OUT_REG(GLAMO_REG_2D_DST_Y, dstY);
++	OUT_REG(GLAMO_REG_2D_RECT_WIDTH, w);
++	OUT_REG(GLAMO_REG_2D_RECT_HEIGHT, h);
++	OUT_REG(GLAMO_REG_2D_COMMAND3, 0);
++	OUT_REG(GLAMO_REG_2D_ID1, 0);
++	OUT_REG(GLAMO_REG_2D_ID2, 0);
++	END_DMA();
++}
++
++static void
++GLAMODoneCopy(void)
++{
++	ENTER_DRAW(0);
++	LEAVE_DRAW(0);
++}
++
++static Bool
++GLAMOUploadToScreen(PixmapPtr pDst, char *src, int src_pitch)
++{
++	int width, height, bpp, i;
++	CARD8 *dst_offset;
++	int dst_pitch;
++
++	dst_offset = (CARD8 *)pDst->devPrivate.ptr;
++	dst_pitch = pDst->devKind;
++	width = pDst->drawable.width;
++	height = pDst->drawable.height;
++	bpp = pDst->drawable.bitsPerPixel;
++	bpp /= 8;
++
++	for (i = 0; i < height; i++)
++	{
++		memcpy(dst_offset, src, width * bpp);
++
++		dst_offset += dst_pitch;
++		src += src_pitch;
++	}
++
++	ErrorF("hostdata upload %d,%d %dbpp\n", width, height, bpp);
++
++	return TRUE;
++}
++
++
++#if 0
++static Bool
++GLAMOUploadToScratch(PixmapPtr pSrc, PixmapPtr pDst)
++{
++	KdScreenPriv(pSrc->drawable.pScreen);
++	GLAMOCardInfo(pScreenPriv);
++	GLAMOScreenInfo(pScreenPriv);
++	int dst_pitch, src_pitch, w, i, size, bytes;
++	unsigned char *dst, *src;
++	RING_LOCALS;
++
++	ENTER_DRAW(pSrc);
++	/* Align width to log 2, useful for R128 composite.  This should be a
++	 * KAA flag we check for (and supported in kaa.c in general) since many
++	 * older bits of hardware are going to want POT pitches.
++	 */
++	w = pSrc->drawable.width;
++	if (glamos->kaa.flags & KAA_OFFSCREEN_ALIGN_POT)
++		w = 1 << (GLAMOLog2(w - 1) + 1);
++	dst_pitch = (w * pSrc->drawable.bitsPerPixel / 8 +
++	    glamos->kaa.pitchAlign - 1) & ~(glamos->kaa.pitchAlign - 1);
++
++	size = dst_pitch * pSrc->drawable.height;
++	if (size > glamos->scratch_area->size)
++		GLAMO_FALLBACK(("Pixmap too large for scratch (%d,%d)\n",
++		    pSrc->drawable.width, pSrc->drawable.height));
++
++	glamos->scratch_next = (glamos->scratch_next + glamos->kaa.offsetAlign - 1) &
++	    ~(glamos->kaa.offsetAlign - 1);
++	if (glamos->scratch_next + size > glamos->scratch_area->offset +
++	    glamos->scratch_area->size) {
++		/* Only sync when we've used all of the scratch area. */
++		kaaWaitSync(pSrc->drawable.pScreen);
++		glamos->scratch_next = glamos->scratch_area->offset;
++	}
++	memcpy(pDst, pSrc, sizeof(*pDst));
++	pDst->devKind = dst_pitch;
++	pDst->devPrivate.ptr = pScreenPriv->screen->memory_base +
++	    glamos->scratch_next;
++	glamos->scratch_next += size;
++
++	src = pSrc->devPrivate.ptr;
++	src_pitch = pSrc->devKind;
++	dst = pDst->devPrivate.ptr;
++	bytes = src_pitch < dst_pitch ? src_pitch : dst_pitch;
++
++	i = pSrc->drawable.height;
++	while (i--) {
++		memcpy(dst, src, bytes);
++		dst += dst_pitch;
++		src += src_pitch;
++	}
++
++	/* Flush the pixel cache */
++	if (glamoc->is_3362) {
++		BEGIN_DMA(4);
++		OUT_REG(RADEON_REG_RB3D_DSTCACHE_CTLSTAT,
++		    RADEON_RB3D_DC_FLUSH_ALL);
++		OUT_REG(GLAMO_REG_WAIT_UNTIL, RADEON_WAIT_HOST_IDLECLEAN);
++		END_DMA();
++	} else {
++		BEGIN_DMA(2);
++		OUT_REG(R128_REG_PC_GUI_CTLSTAT, R128_PC_FLUSH_ALL);
++		END_DMA();
++	}
++
++	LEAVE_DRAW(pSrc);
++	return TRUE;
++}
++#endif
++
++static void
++GLAMOBlockHandler(pointer blockData, OSTimePtr timeout, pointer readmask)
++{
++	ScreenPtr pScreen = (ScreenPtr) blockData;
++	KdScreenPriv(pScreen);
++	GLAMOScreenInfo(pScreenPriv);
++
++	/* When the server is going to sleep, make sure that all DMA data has
++	 * been flushed.
++	 */
++	if (glamos->indirectBuffer)
++		GLAMOFlushIndirect(glamos, 1);
++}
++
++static void
++GLAMOWakeupHandler(pointer blockData, int result, pointer readmask)
++{
++}
++
++Bool
++GLAMODrawInit(ScreenPtr pScreen)
++{
++	KdScreenPriv(pScreen);
++	GLAMOScreenInfo(pScreenPriv);
++
++	ErrorF("Screen: %d/%d depth/bpp\n", pScreenPriv->screen->fb[0].depth,
++	    pScreenPriv->screen->fb[0].bitsPerPixel);
++
++	RegisterBlockAndWakeupHandlers(GLAMOBlockHandler, GLAMOWakeupHandler,
++	    pScreen);
++
++	glamos->using_dri = FALSE;
++#ifdef USE_DRI
++	glamos->using_dri = GLAMODRIScreenInit(pScreen);
++#endif /* USE_DRI */
++
++	memset(&glamos->kaa, 0, sizeof(KaaScreenInfoRec));
++	glamos->kaa.waitMarker = GLAMOWaitMarker;
++	glamos->kaa.PrepareSolid = GLAMOPrepareSolid;
++	glamos->kaa.Solid = GLAMOSolid;
++	glamos->kaa.DoneSolid = GLAMODoneSolid;
++	glamos->kaa.PrepareCopy = GLAMOPrepareCopy;
++	glamos->kaa.Copy = GLAMOCopy;
++	glamos->kaa.DoneCopy = GLAMODoneCopy;
++	/* Other acceleration will be hooked in in DrawEnable depending on
++	 * what type of DMA gets initialized.
++	 */
++
++	glamos->kaa.flags = KAA_OFFSCREEN_PIXMAPS;
++	glamos->kaa.offsetAlign = 2;
++	glamos->kaa.pitchAlign = 2;
++
++	kaaInitTrapOffsets(8, sample_offsets_x, sample_offsets_y, 0.0, 0.0);
++	sample_count = (1 << 8) - 1;
++
++	if (!kaaDrawInit(pScreen, &glamos->kaa))
++		return FALSE;
++
++	return TRUE;
++}
++
++#if 0
++static void
++GLAMOScratchSave(ScreenPtr pScreen, KdOffscreenArea *area)
++{
++	KdScreenPriv(pScreen);
++	GLAMOScreenInfo(pScreenPriv);
++
++	glamos->scratch_area = NULL;
++}
++#endif
++
++void
++GLAMODrawEnable(ScreenPtr pScreen)
++{
++	KdScreenPriv(pScreen);
++	GLAMOScreenInfo(pScreenPriv);
++
++	GLAMODMASetup(pScreen);
++	GLAMODrawSetup(pScreen);
++
++	glamos->scratch_area = NULL;
++	glamos->kaa.PrepareBlend = NULL;
++	glamos->kaa.Blend = NULL;
++	glamos->kaa.DoneBlend = NULL;
++	glamos->kaa.CheckComposite = NULL;
++	glamos->kaa.PrepareComposite = NULL;
++	glamos->kaa.Composite = NULL;
++	glamos->kaa.DoneComposite = NULL;
++	glamos->kaa.UploadToScreen = NULL;
++    	glamos->kaa.UploadToScratch = NULL;
++
++#ifdef USE_DRI
++	if (glamos->using_dri) {
++		if (!glamoc->is_3362) {
++			/*glamos->kaa.PrepareTrapezoids = R128PrepareTrapezoids;
++			glamos->kaa.Trapezoids = R128Trapezoids;
++			glamos->kaa.DoneTrapezoids = R128DoneTrapezoids;*/
++		} else if (glamoc->is_r100 || glamoc->is_r200) {
++			glamos->kaa.PrepareTrapezoids = RadeonPrepareTrapezoids;
++			glamos->kaa.Trapezoids = RadeonTrapezoids;
++			glamos->kaa.DoneTrapezoids = RadeonDoneTrapezoids;
++		}
++	}
++#endif /* USE_DRI */
++
++	glamos->kaa.UploadToScreen = GLAMOUploadToScreen;
++
++	/* Reserve a scratch area.  It'll be used for storing glyph data during
++	 * Composite operations, because glyphs aren't in real pixmaps and thus
++	 * can't be migrated.
++	 */
++#if 0
++	glamos->scratch_area = KdOffscreenAlloc(pScreen, 131072,
++	    glamos->kaa.offsetAlign, TRUE, GLAMOScratchSave, glamos);
++	if (glamos->scratch_area != NULL) {
++		glamos->scratch_next = glamos->scratch_area->offset;
++		glamos->kaa.UploadToScratch = GLAMOUploadToScratch;
++	}
++#endif
++
++	kaaMarkSync(pScreen);
++}
++
++void
++GLAMODrawDisable(ScreenPtr pScreen)
++{
++	kaaWaitSync(pScreen);
++	GLAMODMATeardown(pScreen);
++}
++
++void
++GLAMODrawFini(ScreenPtr pScreen)
++{
++#ifdef USE_DRI
++	KdScreenPriv(pScreen);
++	GLAMOScreenInfo(pScreenPriv);
++	if (glamos->using_dri) {
++		GLAMODRICloseScreen(pScreen);
++		glamos->using_dri = FALSE;
++	}
++#endif /* USE_DRI */
++
++	RemoveBlockAndWakeupHandlers(GLAMOBlockHandler, GLAMOWakeupHandler,
++	    pScreen);
++
++	kaaDrawFini(pScreen);
++}
++
+Index: xserver/hw/kdrive/glamo/glamo_draw.h
+===================================================================
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ xserver/hw/kdrive/glamo/glamo_draw.h	2007-09-25 19:02:01.000000000 +0800
+@@ -0,0 +1,59 @@
++/*
++ * Copyright � 2007 OpenMoko, Inc.
++ *
++ * This driver is based on Xati,
++ * Copyright � 2004 Eric Anholt
++ *
++ * Permission to use, copy, modify, distribute, and sell this software and its
++ * documentation for any purpose is hereby granted without fee, provided that
++ * the above copyright notice appear in all copies and that both that copyright
++ * notice and this permission notice appear in supporting documentation, and
++ * that the name of the copyright holders not be used in advertising or
++ * publicity pertaining to distribution of the software without specific,
++ * written prior permission.  The copyright holders make no representations
++ * about the suitability of this software for any purpose.  It is provided "as
++ * is" without express or implied warranty.
++ *
++ * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
++ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
++ * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
++ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
++ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
++ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
++ * OF THIS SOFTWARE.
++ */
++
++#ifndef _GLAMO_DRAW_H_
++#define _GLAMO_DRAW_H_
++
++void GLAMOWaitIdle(GLAMOScreenInfo *glamos);
++
++#define GLAMO_TRACE_FALL 1
++#define GLAMO_TRACE_DRAW 1
++
++#if GLAMO_TRACE_FALL
++#define GLAMO_FALLBACK(x)			\
++do {					\
++	ErrorF("%s: ", __FUNCTION__);	\
++	ErrorF x;			\
++	return FALSE;			\
++} while (0)
++#else
++#define GLAMO_FALLBACK(x) return FALSE
++#endif
++
++#if GLAMO_TRACE_DRAW
++#define ENTER_DRAW(pix) GLAMOEnterDraw(pix, __FUNCTION__)
++#define LEAVE_DRAW(pix) GLAMOLeaveDraw(pix, __FUNCTION__)
++
++void
++GLAMOEnterDraw (PixmapPtr pPixmap, const char *function);
++
++void
++GLAMOLeaveDraw (PixmapPtr pPixmap, const char *function);
++#else /* GLAMO_TRACE */
++#define ENTER_DRAW(pix)
++#define LEAVE_DRAW(pix)
++#endif /* !GLAMO_TRACE */
++
++#endif /* _GLAMO_DRAW_H_ */
+Index: xserver/hw/kdrive/glamo/glamo_stub.c
+===================================================================
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ xserver/hw/kdrive/glamo/glamo_stub.c	2007-09-26 17:45:27.000000000 +0800
+@@ -0,0 +1,84 @@
++/*
++ * Copyright � 2007 OpenMoko, Inc.
++ *
++ * This driver is based on Xati,
++ * Copyright � 2003 Eric Anholt
++ *
++ * Permission to use, copy, modify, distribute, and sell this software and its
++ * documentation for any purpose is hereby granted without fee, provided that
++ * the above copyright notice appear in all copies and that both that copyright
++ * notice and this permission notice appear in supporting documentation, and
++ * that the name of the copyright holders not be used in advertising or
++ * publicity pertaining to distribution of the software without specific,
++ * written prior permission.  The copyright holders make no representations
++ * about the suitability of this software for any purpose.  It is provided "as
++ * is" without express or implied warranty.
++ *
++ * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
++ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
++ * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
++ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
++ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
++ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
++ * OF THIS SOFTWARE.
++ */
++
++#ifdef HAVE_CONFIG_H
++#include <kdrive-config.h>
++#endif
++#include "glamo.h"
++#include "klinux.h"
++
++void
++InitCard(char *name)
++{
++	KdCardAttr attr;
++
++	attr.io = 0;
++	attr.address[0] = 0x8000000;
++	attr.naddr = 1;
++	KdCardInfoAdd(&GLAMOFuncs, &attr, 0);
++}
++
++void
++InitOutput(ScreenInfo *pScreenInfo, int argc, char **argv)
++{
++	KdInitOutput(pScreenInfo, argc, argv);
++}
++
++void
++InitInput(int argc, char **argv)
++{
++	KdKeyboardInfo *ki;
++
++	KdAddKeyboardDriver(&LinuxKeyboardDriver);
++	KdAddPointerDriver(&LinuxMouseDriver);
++#ifdef TSLIB
++	KdAddPointerDriver(&TsDriver);
++#endif
++
++	ki = KdParseKeyboard("keybd");
++	KdAddKeyboard(ki);
++}
++
++void
++ddxUseMsg (void)
++{
++	KdUseMsg();
++#ifdef KDRIVEVESA
++	vesaUseMsg();
++#endif
++}
++
++int
++ddxProcessArgument(int argc, char **argv, int i)
++{
++	int	ret;
++
++#ifdef KDRIVEVESA
++	if (!(ret = vesaProcessArgument (argc, argv, i)))
++#endif
++		ret = KdProcessArgument(argc, argv, i);
++
++	return ret;
++}
+Index: xserver/hw/kdrive/glamo/glamo_video.c
+===================================================================
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ xserver/hw/kdrive/glamo/glamo_video.c	2007-09-26 17:47:55.000000000 +0800
+@@ -0,0 +1,798 @@
++/*
++ * Copyright � 2007 OpenMoko, Inc.
++ *
++ * This driver is based on Xati,
++ * Copyright � 2004 Keith Packard
++ * Copyright � 2005 Eric Anholt
++ *
++ * Permission to use, copy, modify, distribute, and sell this software and its
++ * documentation for any purpose is hereby granted without fee, provided that
++ * the above copyright notice appear in all copies and that both that copyright
++ * notice and this permission notice appear in supporting documentation, and
++ * that the name of the copyright holders not be used in advertising or
++ * publicity pertaining to distribution of the software without specific,
++ * written prior permission.  The copyright holders make no representations
++ * about the suitability of this software for any purpose.  It is provided "as
++ * is" without express or implied warranty.
++ *
++ * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
++ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
++ * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
++ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
++ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
++ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
++ * OF THIS SOFTWARE.
++ */
++
++#ifdef HAVE_CONFIG_H
++#include <kdrive-config.h>
++#endif
++#include "glamo.h"
++#include "glamo_dma.h"
++#include "glamo_draw.h"
++#include "glamo-regs.h"
++#include "kaa.h"
++
++#include <X11/extensions/Xv.h>
++#include "fourcc.h"
++
++#define MAKE_ATOM(a) MakeAtom(a, sizeof(a) - 1, TRUE)
++
++static Atom xvBrightness, xvSaturation;
++
++#define IMAGE_MAX_WIDTH		2048
++#define IMAGE_MAX_HEIGHT	2048
++
++static void
++GLAMOStopVideo(KdScreenInfo *screen, pointer data, Bool exit)
++{
++	ScreenPtr pScreen = screen->pScreen;
++	GLAMOPortPrivPtr pPortPriv = (GLAMOPortPrivPtr)data;
++
++	REGION_EMPTY(screen->pScreen, &pPortPriv->clip);
++
++	if (pPortPriv->off_screen) {
++		KdOffscreenFree (pScreen, pPortPriv->off_screen);
++		pPortPriv->off_screen = 0;
++	}
++}
++
++static int
++GLAMOSetPortAttribute(KdScreenInfo *screen, Atom attribute, int value,
++    pointer data)
++{
++	return BadMatch;
++}
++
++static int
++GLAMOGetPortAttribute(KdScreenInfo *screen, Atom attribute, int *value,
++    pointer data)
++{
++	return BadMatch;
++}
++
++static void
++GLAMOQueryBestSize(KdScreenInfo *screen, Bool motion, short vid_w, short vid_h,
++    short drw_w, short drw_h, unsigned int *p_w, unsigned int *p_h,
++    pointer data)
++{
++	*p_w = drw_w;
++	*p_h = drw_h;
++}
++
++/* GLAMOClipVideo -
++
++   Takes the dst box in standard X BoxRec form (top and left
++   edges inclusive, bottom and right exclusive).  The new dst
++   box is returned.  The source boundaries are given (x1, y1
++   inclusive, x2, y2 exclusive) and returned are the new source
++   boundaries in 16.16 fixed point.
++*/
++
++static void
++GLAMOClipVideo(BoxPtr dst, INT32 *x1, INT32 *x2, INT32 *y1, INT32 *y2,
++    BoxPtr extents, INT32 width, INT32 height)
++{
++	INT32 vscale, hscale, delta;
++	int diff;
++
++	hscale = ((*x2 - *x1) << 16) / (dst->x2 - dst->x1);
++	vscale = ((*y2 - *y1) << 16) / (dst->y2 - dst->y1);
++
++	*x1 <<= 16; *x2 <<= 16;
++	*y1 <<= 16; *y2 <<= 16;
++
++	diff = extents->x1 - dst->x1;
++	if (diff > 0) {
++		dst->x1 = extents->x1;
++		*x1 += diff * hscale;
++	}
++	diff = dst->x2 - extents->x2;
++	if (diff > 0) {
++		dst->x2 = extents->x2;
++		*x2 -= diff * hscale;
++	}
++	diff = extents->y1 - dst->y1;
++	if (diff > 0) {
++		dst->y1 = extents->y1;
++		*y1 += diff * vscale;
++	}
++	diff = dst->y2 - extents->y2;
++	if (diff > 0) {
++		dst->y2 = extents->y2;
++		*y2 -= diff * vscale;
++	}
++
++	if (*x1 < 0) {
++		diff =  (- *x1 + hscale - 1)/ hscale;
++		dst->x1 += diff;
++		*x1 += diff * hscale;
++	}
++	delta = *x2 - (width << 16);
++	if (delta > 0) {
++		diff = (delta + hscale - 1)/ hscale;
++		dst->x2 -= diff;
++		*x2 -= diff * hscale;
++	}
++	if (*y1 < 0) {
++		diff =  (- *y1 + vscale - 1)/ vscale;
++		dst->y1 += diff;
++		*y1 += diff * vscale;
++	}
++	delta = *y2 - (height << 16);
++	if (delta > 0) {
++		diff = (delta + vscale - 1)/ vscale;
++		dst->y2 -= diff;
++		*y2 -= diff * vscale;
++	}
++}
++
++static void
++GlamoDisplayVideo(KdScreenInfo *screen, GLAMOPortPrivPtr pPortPriv)
++{
++	ScreenPtr pScreen = screen->pScreen;
++	KdScreenPriv(pScreen);
++	GLAMOScreenInfo(pScreenPriv);
++	PixmapPtr pPixmap = pPortPriv->pPixmap;
++	CARD32 dst_offset, dst_pitch;
++	int dstxoff, dstyoff, srcDatatype;
++	RING_LOCALS;
++
++	BoxPtr pBox = REGION_RECTS(&pPortPriv->clip);
++	int nBox = REGION_NUM_RECTS(&pPortPriv->clip);
++
++	dst_offset = ((CARD8 *)pPixmap->devPrivate.ptr -
++	    pScreenPriv->screen->memory_base);
++	dst_pitch = pPixmap->devKind;
++
++#ifdef COMPOSITE
++	dstxoff = -pPixmap->screen_x + pPixmap->drawable.x;
++	dstyoff = -pPixmap->screen_y + pPixmap->drawable.y;
++#else
++	dstxoff = 0;
++	dstyoff = 0;
++#endif
++
++	BEGIN_DMA(14);
++	OUT_REG(GLAMO_REG_ISP_YUV2RGB_11, 0x0167);
++	OUT_REG(GLAMO_REG_ISP_YUV2RGB_21, 0x01c5);
++	OUT_REG(GLAMO_REG_ISP_YUV2RGB_32, 0x00b6);
++	OUT_REG(GLAMO_REG_ISP_YUV2RGB_33, 0x0058);
++	OUT_REG(GLAMO_REG_ISP_YUV2RGB_RG, 0xb3 << 8 | 0x89);
++	OUT_REG(GLAMO_REG_ISP_YUV2RGB_B, 0xe2);
++
++	/* TODO weight matrix */
++
++	OUT_REG(GLAMO_REG_ISP_PORT2_EN, GLAMO_ISP_PORT2_EN_DECODE);
++
++	END_DMA();
++
++	if (pPortPriv->id == FOURCC_UYVY)
++		srcDatatype = 3;
++	else
++		srcDatatype = 1;
++
++	BEGIN_DMA(8);
++#if 0
++	OUT_REG(GLAMO_REG_ISP_EN3, GLAMO_ISP_EN3_SCALE_IMPROVE |
++				   GLAMO_ISP_EN3_PLANE_MODE |
++				   GLAMO_ISP_EN3_YUV_INPUT |
++				   GLAMO_ISP_EN3_YUV420);
++	OUT_REG(GLAMO_REG_ISP_PORT1_DEC_EN, GLAMO_ISP_PORT1_EN_OUTPUT);
++
++	OUT_REG(GLAMO_REG_ISP_DEC_SCALEH, 1 << 11);
++	OUT_REG(GLAMO_REG_ISP_DEC_SCALEV, 1 << 11);
++
++	{
++		struct {
++			int src_block_y;
++			int src_block_x;
++			int src_block_h;
++			int src_block_w;
++			int jpeg_out_y;
++			int jpeg_out_x;
++			int fifo_full_cnt;
++			int in_length;
++			int fifo_data_cnt;
++			int in_height;
++		} onfly;
++
++		onfly.src_block_y = 32;
++		onfly.src_block_x = 32;
++		onfly.src_block_h = 36;
++		onfly.src_block_w = 35;
++		onfly.jpeg_out_y = 32;
++		onfly.jpeg_out_x = 32;
++		onfly.fifo_full_cnt = 0;
++		onfly.in_length = onfly.jpeg_out_x + 3;
++		onfly.fifo_data_cnt = onfly.src_block_w * onfly.src_block_h / 2;
++		onfly.in_height = onfly.jpeg_out_y + 2;
++
++		OUT_REG(GLAMO_REG_ISP_ONFLY_MODE1, onfly.src_block_y << 10 | onfly.src_block_x << 2);
++		OUT_REG(GLAMO_REG_ISP_ONFLY_MODE2, onfly.src_block_h << 8 | onfly.src_block_w);
++		OUT_REG(GLAMO_REG_ISP_ONFLY_MODE3, onfly.jpeg_out_y << 8 | onfly.jpeg_out_x);
++		OUT_REG(GLAMO_REG_ISP_ONFLY_MODE4, onfly.fifo_full_cnt << 8 | onfly.in_length);
++		OUT_REG(GLAMO_REG_ISP_ONFLY_MODE5, onfly.fifo_data_cnt << 6 | onfly.in_height);
++	}
++#endif
++
++	OUT_REG(GLAMO_REG_ISP_EN1,
++		GLAMO_ISP_EN1_YUV420 |
++		GLAMO_ISP_EN1_YUV_INPUT |
++		GLAMO_ISP_EN1_YUV_PACK |
++		((srcDatatype << 4) & 0x7));
++
++	OUT_REG(GLAMO_REG_ISP_PORT1_CAP_EN,
++		GLAMO_ISP_PORT1_EN_OUTPUT);
++
++	OUT_REG(GLAMO_REG_ISP_CAP_PITCH, pPortPriv->src_pitch);
++	OUT_REG(GLAMO_REG_ISP_PORT1_CAP_PITCH, dst_pitch);
++
++	END_DMA();
++
++	while (nBox--) {
++		int srcX, srcY, dstX, dstY, srcw, srch, dstw, dsth;
++		CARD32 srcO, dstO;
++
++		dstX = pBox->x1 + dstxoff;
++		dstY = pBox->y1 + dstyoff;
++		dstw = pBox->x2 - pBox->x1;
++		dsth = pBox->y2 - pBox->y1;
++		srcX = (pBox->x1 - pPortPriv->dst_x1) *
++		    pPortPriv->src_w / pPortPriv->dst_w;
++		srcY = (pBox->y1 - pPortPriv->dst_y1) *
++		    pPortPriv->src_h / pPortPriv->dst_h;
++		srcw = pPortPriv->src_w - srcX; /* XXX */
++		srch = pPortPriv->src_h - srcY; /* XXX */
++
++		srcO = pPortPriv->src_offset + srcY * pPortPriv->src_pitch + srcX * 2;
++		dstO = dst_offset + dstY * dst_pitch + dstX * 2;
++
++		BEGIN_DMA(18);
++
++		OUT_REG(GLAMO_REG_ISP_CAP_0_ADDRL, srcO & 0xffff);
++		OUT_REG(GLAMO_REG_ISP_CAP_0_ADDRH, (srcO >> 16) & 0x7f);
++		OUT_REG(GLAMO_REG_ISP_CAP_HEIGHT, srch);
++		OUT_REG(GLAMO_REG_ISP_CAP_WIDTH, srcw);
++
++		OUT_REG(GLAMO_REG_ISP_PORT1_CAP_0_ADDRL, dstO & 0xffff);
++		OUT_REG(GLAMO_REG_ISP_PORT1_CAP_0_ADDRH, (dstO >> 16) & 0x7f);
++		OUT_REG(GLAMO_REG_ISP_PORT1_CAP_WIDTH, dstw);
++		OUT_REG(GLAMO_REG_ISP_PORT1_CAP_HEIGHT, dsth);
++
++		/* fire */
++		OUT_REG(GLAMO_REG_ISP_EN1, GLAMO_ISP_EN1_FIRE_ISP);
++		OUT_REG(GLAMO_REG_ISP_EN1, 0);
++
++		END_DMA();
++
++		GLAMOWaitIdle(glamos);
++
++		pBox++;
++	}
++#ifdef DAMAGEEXT
++	/* XXX: Shouldn't this be in kxv.c instead? */
++	DamageDamageRegion(pPortPriv->pDraw, &pPortPriv->clip);
++#endif
++	kaaMarkSync(pScreen);
++}
++
++static void
++GLAMOVideoSave(ScreenPtr pScreen, KdOffscreenArea *area)
++{
++	KdScreenPriv(pScreen);
++	GLAMOScreenInfo(pScreenPriv);
++	GLAMOPortPrivPtr pPortPriv = glamos->pAdaptor->pPortPrivates[0].ptr;
++
++	if (pPortPriv->off_screen == area)
++		pPortPriv->off_screen = 0;
++}
++
++static int
++GLAMOPutImage(KdScreenInfo *screen, DrawablePtr pDraw,
++	       short src_x, short src_y,
++	       short drw_x, short drw_y,
++	       short src_w, short src_h,
++	       short drw_w, short drw_h,
++	       int id,
++	       unsigned char *buf,
++	       short width,
++	       short height,
++	       Bool sync,
++	       RegionPtr clipBoxes,
++	       pointer data)
++{
++	ScreenPtr pScreen = screen->pScreen;
++	KdScreenPriv(pScreen);
++	GLAMOCardInfo(pScreenPriv);
++	GLAMOScreenInfo(pScreenPriv);
++	GLAMOPortPrivPtr pPortPriv = (GLAMOPortPrivPtr)data;
++	char *mmio = glamoc->reg_base;
++	INT32 x1, x2, y1, y2;
++	int randr = RR_Rotate_0 /* XXX */;
++	int srcPitch, srcPitch2, dstPitch;
++	int top, left, npixels, nlines, size;
++	BoxRec dstBox;
++	int dst_width = width, dst_height = height;
++	int rot_x1, rot_y1, rot_x2, rot_y2;
++	int dst_x1, dst_y1, dst_x2, dst_y2;
++	int rot_src_w, rot_src_h, rot_drw_w, rot_drw_h;
++
++	/* Clip */
++	x1 = src_x;
++	x2 = src_x + src_w;
++	y1 = src_y;
++	y2 = src_y + src_h;
++
++	dstBox.x1 = drw_x;
++	dstBox.x2 = drw_x + drw_w;
++	dstBox.y1 = drw_y;
++	dstBox.y2 = drw_y + drw_h;
++
++	GLAMOClipVideo(&dstBox, &x1, &x2, &y1, &y2,
++	    REGION_EXTENTS(pScreen, clipBoxes), width, height);
++
++	src_w = (x2 - x1) >> 16;
++	src_h = (y2 - y1) >> 16;
++	drw_w = dstBox.x2 - dstBox.x1;
++	drw_h = dstBox.y2 - dstBox.y1;
++
++	if ((x1 >= x2) || (y1 >= y2))
++		return Success;
++
++	if (mmio == NULL)
++		return BadAlloc;
++
++	if (randr & (RR_Rotate_0|RR_Rotate_180)) {
++		dst_width = width;
++		dst_height = height;
++		rot_src_w = src_w;
++		rot_src_h = src_h;
++		rot_drw_w = drw_w;
++		rot_drw_h = drw_h;
++	} else {
++		dst_width = height;
++		dst_height = width;
++		rot_src_w = src_h;
++		rot_src_h = src_w;
++		rot_drw_w = drw_h;
++		rot_drw_h = drw_w;
++	}
++
++	switch (randr & RR_Rotate_All) {
++	case RR_Rotate_0:
++	default:
++		dst_x1 = dstBox.x1;
++		dst_y1 = dstBox.y1;
++		dst_x2 = dstBox.x2;
++		dst_y2 = dstBox.y2;
++		rot_x1 = x1;
++		rot_y1 = y1;
++		rot_x2 = x2;
++		rot_y2 = y2;
++		break;
++	case RR_Rotate_90:
++		dst_x1 = dstBox.y1;
++		dst_y1 = screen->height - dstBox.x2;
++		dst_x2 = dstBox.y2;
++		dst_y2 = screen->height - dstBox.x1;
++		rot_x1 = y1;
++		rot_y1 = (src_w << 16) - x2;
++		rot_x2 = y2;
++		rot_y2 = (src_w << 16) - x1;
++		break;
++	case RR_Rotate_180:
++		dst_x1 = screen->width - dstBox.x2;
++		dst_y1 = screen->height - dstBox.y2;
++		dst_x2 = screen->width - dstBox.x1;
++		dst_y2 = screen->height - dstBox.y1;
++		rot_x1 = (src_w << 16) - x2;
++		rot_y1 = (src_h << 16) - y2;
++		rot_x2 = (src_w << 16) - x1;
++		rot_y2 = (src_h << 16) - y1;
++		break;
++	case RR_Rotate_270:
++		dst_x1 = screen->width - dstBox.y2;
++		dst_y1 = dstBox.x1;
++		dst_x2 = screen->width - dstBox.y1;
++		dst_y2 = dstBox.x2;
++		rot_x1 = (src_h << 16) - y2;
++		rot_y1 = x1;
++		rot_x2 = (src_h << 16) - y1;
++		rot_y2 = x2;
++		break;
++	}
++
++	switch(id) {
++	case FOURCC_YV12:
++	case FOURCC_I420:
++		dstPitch = ((dst_width << 1) + 15) & ~15;
++		srcPitch = (width + 3) & ~3;
++		srcPitch2 = ((width >> 1) + 3) & ~3;
++		size = dstPitch * dst_height;
++		break;
++	case FOURCC_UYVY:
++	case FOURCC_YUY2:
++	default:
++		dstPitch = ((dst_width << 1) + 15) & ~15;
++		srcPitch = (width << 1);
++		srcPitch2 = 0;
++		size = dstPitch * dst_height;
++		break;
++	}
++
++	if (pPortPriv->off_screen != NULL && size != pPortPriv->size) {
++		KdOffscreenFree(screen->pScreen, pPortPriv->off_screen);
++		pPortPriv->off_screen = 0;
++	}
++
++	if (pPortPriv->off_screen == NULL) {
++		pPortPriv->off_screen = KdOffscreenAlloc(screen->pScreen,
++		    size * 2, 64, TRUE, GLAMOVideoSave, pPortPriv);
++		if (pPortPriv->off_screen == NULL)
++			return BadAlloc;
++	}
++
++
++	if (pDraw->type == DRAWABLE_WINDOW)
++		pPortPriv->pPixmap =
++		    (*pScreen->GetWindowPixmap)((WindowPtr)pDraw);
++	else
++		pPortPriv->pPixmap = (PixmapPtr)pDraw;
++
++	/* Migrate the pixmap to offscreen if necessary. */
++	if (!kaaPixmapIsOffscreen(pPortPriv->pPixmap))
++		kaaMoveInPixmap(pPortPriv->pPixmap);
++
++	if (!kaaPixmapIsOffscreen(pPortPriv->pPixmap)) {
++		return BadAlloc;
++	}
++
++	pPortPriv->src_offset = pPortPriv->off_screen->offset;
++	pPortPriv->src_addr = (CARD8 *)(pScreenPriv->screen->memory_base +
++	    pPortPriv->src_offset);
++	pPortPriv->src_pitch = dstPitch;
++	pPortPriv->size = size;
++	pPortPriv->pDraw = pDraw;
++
++	/* copy data */
++	top = rot_y1 >> 16;
++	left = (rot_x1 >> 16) & ~1;
++	npixels = ((((rot_x2 + 0xffff) >> 16) + 1) & ~1) - left;
++
++	/* Since we're probably overwriting the area that might still be used
++	 * for the last PutImage request, wait for idle.
++	 */
++	GLAMOWaitIdle(glamos);
++
++	switch(id) {
++	case FOURCC_YV12:
++	case FOURCC_I420:
++		top &= ~1;
++		nlines = ((((rot_y2 + 0xffff) >> 16) + 1) & ~1) - top;
++		/* pack the source as YUY2 to vram */
++		KdXVCopyPlanarData(screen, buf, pPortPriv->src_addr, randr,
++		    srcPitch, srcPitch2, dstPitch, rot_src_w, rot_src_h,
++		    height, top, left, nlines, npixels, id);
++		break;
++	case FOURCC_UYVY:
++	case FOURCC_YUY2:
++	default:
++		nlines = ((rot_y2 + 0xffff) >> 16) - top;
++		KdXVCopyPackedData(screen, buf, pPortPriv->src_addr, randr,
++		    srcPitch, dstPitch, rot_src_w, rot_src_h, top, left,
++		    nlines, npixels);
++		break;
++	}
++
++	/* update cliplist */
++	if (!REGION_EQUAL(screen->pScreen, &pPortPriv->clip, clipBoxes)) {
++		REGION_COPY(screen->pScreen, &pPortPriv->clip, clipBoxes);
++	}
++
++	pPortPriv->id = id;
++	pPortPriv->src_x1 = rot_x1;
++	pPortPriv->src_y1 = rot_y1;
++	pPortPriv->src_x2 = rot_x2;
++	pPortPriv->src_y2 = rot_y2;
++	pPortPriv->src_w = rot_src_w;
++	pPortPriv->src_h = rot_src_h;
++	pPortPriv->dst_x1 = dst_x1;
++	pPortPriv->dst_y1 = dst_y1;
++	pPortPriv->dst_x2 = dst_x2;
++	pPortPriv->dst_y2 = dst_y2;
++	pPortPriv->dst_w = rot_drw_w;
++	pPortPriv->dst_h = rot_drw_h;
++
++	GlamoDisplayVideo(screen, pPortPriv);
++
++	return Success;
++}
++
++static int
++GLAMOReputImage(KdScreenInfo *screen, DrawablePtr pDraw, short drw_x, short drw_y,
++    RegionPtr clipBoxes, pointer data)
++{
++	ScreenPtr pScreen = screen->pScreen;
++	GLAMOPortPrivPtr	pPortPriv = (GLAMOPortPrivPtr)data;
++	BoxPtr pOldExtents = REGION_EXTENTS(screen->pScreen, &pPortPriv->clip);
++	BoxPtr pNewExtents = REGION_EXTENTS(screen->pScreen, clipBoxes);
++
++	if (pOldExtents->x1 != pNewExtents->x1 ||
++	    pOldExtents->x2 != pNewExtents->x2 ||
++	    pOldExtents->y1 != pNewExtents->y1 ||
++	    pOldExtents->y2 != pNewExtents->y2)
++		return BadMatch;
++
++	if (pDraw->type == DRAWABLE_WINDOW)
++		pPortPriv->pPixmap =
++		    (*pScreen->GetWindowPixmap)((WindowPtr)pDraw);
++	else
++		pPortPriv->pPixmap = (PixmapPtr)pDraw;
++
++	if (!kaaPixmapIsOffscreen(pPortPriv->pPixmap))
++		kaaMoveInPixmap(pPortPriv->pPixmap);
++
++	if (!kaaPixmapIsOffscreen(pPortPriv->pPixmap)) {
++		ErrorF("err\n");
++		return BadAlloc;
++	}
++
++
++	/* update cliplist */
++	if (!REGION_EQUAL(screen->pScreen, &pPortPriv->clip, clipBoxes))
++		REGION_COPY(screen->pScreen, &pPortPriv->clip, clipBoxes);
++
++	/* XXX: What do the drw_x and drw_y here mean for us? */
++
++	GlamoDisplayVideo(screen, pPortPriv);
++
++	return Success;
++}
++
++static int
++GLAMOQueryImageAttributes(KdScreenInfo *screen, int id, unsigned short *w,
++    unsigned short *h, int *pitches, int *offsets)
++{
++	int size, tmp;
++
++	if (*w > IMAGE_MAX_WIDTH)
++		*w = IMAGE_MAX_WIDTH;
++	if (*h > IMAGE_MAX_HEIGHT)
++		*h = IMAGE_MAX_HEIGHT;
++
++	*w = (*w + 1) & ~1;
++	if (offsets)
++		offsets[0] = 0;
++
++	switch (id)
++	{
++	case FOURCC_YV12:
++	case FOURCC_I420:
++		*h = (*h + 1) & ~1;
++		size = (*w + 3) & ~3;
++		if (pitches)
++			pitches[0] = size;
++		size *= *h;
++		if (offsets)
++			offsets[1] = size;
++		tmp = ((*w >> 1) + 3) & ~3;
++		if (pitches)
++			pitches[1] = pitches[2] = tmp;
++		tmp *= (*h >> 1);
++		size += tmp;
++		if (offsets)
++			offsets[2] = size;
++		size += tmp;
++		break;
++	case FOURCC_UYVY:
++	case FOURCC_YUY2:
++	default:
++		size = *w << 1;
++		if (pitches)
++			pitches[0] = size;
++		size *= *h;
++		break;
++	}
++
++	return size;
++}
++
++
++/* client libraries expect an encoding */
++static KdVideoEncodingRec DummyEncoding[1] =
++{
++	{
++		0,
++		"XV_IMAGE",
++		IMAGE_MAX_WIDTH, IMAGE_MAX_HEIGHT,
++		{1, 1}
++	}
++};
++
++#define NUM_FORMATS 1
++
++static KdVideoFormatRec Formats[NUM_FORMATS] =
++{
++	{16, TrueColor}
++};
++
++#define NUM_ATTRIBUTES 0
++
++static KdAttributeRec Attributes[NUM_ATTRIBUTES] =
++{
++};
++
++#define NUM_IMAGES 4
++
++static KdImageRec Images[NUM_IMAGES] =
++{
++	XVIMAGE_YUY2,
++	XVIMAGE_YV12,
++	XVIMAGE_I420,
++	XVIMAGE_UYVY
++};
++
++static KdVideoAdaptorPtr
++GLAMOSetupImageVideo(ScreenPtr pScreen)
++{
++	KdScreenPriv(pScreen);
++	GLAMOScreenInfo(pScreenPriv);
++	KdVideoAdaptorPtr adapt;
++	GLAMOPortPrivPtr pPortPriv;
++	int i;
++
++	glamos->num_texture_ports = 16;
++
++	adapt = xcalloc(1, sizeof(KdVideoAdaptorRec) + glamos->num_texture_ports *
++	    (sizeof(GLAMOPortPrivRec) + sizeof(DevUnion)));
++	if (adapt == NULL)
++		return NULL;
++
++	adapt->type = XvWindowMask | XvInputMask | XvImageMask;
++	adapt->flags = VIDEO_CLIP_TO_VIEWPORT;
++	adapt->name = "GLAMO Texture Video";
++	adapt->nEncodings = 1;
++	adapt->pEncodings = DummyEncoding;
++	adapt->nFormats = NUM_FORMATS;
++	adapt->pFormats = Formats;
++	adapt->nPorts = glamos->num_texture_ports;
++	adapt->pPortPrivates = (DevUnion*)(&adapt[1]);
++
++	pPortPriv =
++	    (GLAMOPortPrivPtr)(&adapt->pPortPrivates[glamos->num_texture_ports]);
++
++	for (i = 0; i < glamos->num_texture_ports; i++)
++		adapt->pPortPrivates[i].ptr = &pPortPriv[i];
++
++	adapt->nAttributes = NUM_ATTRIBUTES;
++	adapt->pAttributes = Attributes;
++	adapt->pImages = Images;
++	adapt->nImages = NUM_IMAGES;
++	adapt->PutVideo = NULL;
++	adapt->PutStill = NULL;
++	adapt->GetVideo = NULL;
++	adapt->GetStill = NULL;
++	adapt->StopVideo = GLAMOStopVideo;
++	adapt->SetPortAttribute = GLAMOSetPortAttribute;
++	adapt->GetPortAttribute = GLAMOGetPortAttribute;
++	adapt->QueryBestSize = GLAMOQueryBestSize;
++	adapt->PutImage = GLAMOPutImage;
++	adapt->ReputImage = GLAMOReputImage;
++	adapt->QueryImageAttributes = GLAMOQueryImageAttributes;
++
++	/* gotta uninit this someplace */
++	REGION_INIT(pScreen, &pPortPriv->clip, NullBox, 0);
++
++	glamos->pAdaptor = adapt;
++
++	xvBrightness = MAKE_ATOM("XV_BRIGHTNESS");
++	xvSaturation = MAKE_ATOM("XV_SATURGLAMOON");
++
++	return adapt;
++}
++
++static void GLAMOPowerUp(ScreenPtr pScreen)
++{
++	GLAMOEngineEnable(pScreen, GLAMO_ENGINE_ISP);
++	GLAMOEngineReset(pScreen, GLAMO_ENGINE_ISP);
++
++	/* HW_DEBUG_0?? */
++	//MMIOSetBitMask(mmio, REG_ISP(0x102), 0x0020, 0);
++}
++
++static void GLAMOPowerDown(ScreenPtr pScreen)
++{
++	GLAMOEngineReset(pScreen, GLAMO_ENGINE_ISP);
++
++	/* ... and stop the clock */
++}
++
++Bool GLAMOInitVideo(ScreenPtr pScreen)
++{
++	KdScreenPriv(pScreen);
++	GLAMOScreenInfo(pScreenPriv);
++	GLAMOCardInfo(pScreenPriv);
++	KdScreenInfo *screen = pScreenPriv->screen;
++	KdVideoAdaptorPtr *adaptors, *newAdaptors = NULL;
++	KdVideoAdaptorPtr newAdaptor = NULL;
++	int num_adaptors;
++
++	glamos->pAdaptor = NULL;
++
++	if (glamoc->reg_base == NULL)
++		return FALSE;
++
++	num_adaptors = KdXVListGenericAdaptors(screen, &adaptors);
++
++	newAdaptor = GLAMOSetupImageVideo(pScreen);
++
++	if (newAdaptor)  {
++		GLAMOPowerUp(pScreen);
++
++		if (!num_adaptors) {
++			num_adaptors = 1;
++			adaptors = &newAdaptor;
++		} else {
++			newAdaptors = xalloc((num_adaptors + 1) *
++			    sizeof(KdVideoAdaptorPtr *));
++			if (newAdaptors) {
++				memcpy(newAdaptors, adaptors, num_adaptors *
++				    sizeof(KdVideoAdaptorPtr));
++				newAdaptors[num_adaptors] = newAdaptor;
++				adaptors = newAdaptors;
++				num_adaptors++;
++			}
++		}
++	}
++
++	if (num_adaptors)
++		KdXVScreenInit(pScreen, adaptors, num_adaptors);
++
++	if (newAdaptors)
++		xfree(newAdaptors);
++
++	return TRUE;
++}
++
++void
++GLAMOFiniVideo(ScreenPtr pScreen)
++{
++	KdScreenPriv(pScreen);
++	GLAMOScreenInfo(pScreenPriv);
++	KdVideoAdaptorPtr adapt = glamos->pAdaptor;
++	GLAMOPortPrivPtr pPortPriv;
++	int i;
++
++	if (!adapt)
++		return;
++
++	GLAMOPowerDown(pScreen);
++
++	for (i = 0; i < glamos->num_texture_ports; i++) {
++		pPortPriv = (GLAMOPortPrivPtr)(&adapt->pPortPrivates[i].ptr);
++		REGION_UNINIT(pScreen, &pPortPriv->clip);
++	}
++	xfree(adapt);
++	glamos->pAdaptor = NULL;
++}
============================================================
--- packages/linux/linux-openmoko_2.6.22.5.bb	7e0cfda05ce43d08a2e2830dc6d3cbe28cf52bd6
+++ packages/linux/linux-openmoko_2.6.22.5.bb	2403ba846329f9d07c4852a702f505eebde7351f
@@ -22,6 +22,7 @@ SRC_URI = "${KERNELORG_MIRROR}/pub/linux
            ${KERNELORG_MIRROR}/pub/linux/kernel/v2.6/patch-${KERNEL_RELEASE}.bz2;patch=1 \
 	       svn://svn.openmoko.org/trunk/src/target/kernel;module=patches;proto=http \
            file://fix-EVIOCGRAB-semantics-2.6.22.5.patch;patch=1 \
+           file://glamo-report-vram-size-to-userspace.patch;patch=1 \
            file://defconfig-${KERNEL_RELEASE}"
 
 S = "${WORKDIR}/linux-${VANILLA_VERSION}"
============================================================
--- packages/xorg-xserver/xserver-kdrive-common.inc	41111959110e4d02e8cbcb965b17cd1d2494d5b9
+++ packages/xorg-xserver/xserver-kdrive-common.inc	243bcb1cf8f6d81256ea0e31b07b0478b9bb5174
@@ -9,6 +9,7 @@ PACKAGES =+ "xserver-kdrive-fbdev \
              xserver-kdrive-xephyr \
              xserver-kdrive-epson \
              xserver-kdrive-ati \
+             xserver-kdrive-glamo \
              xserver-kdrive-chips \
              xserver-kdrive-i810 \
              xserver-kdrive-mach64 \
@@ -32,6 +33,7 @@ DESCRIPTION_xserver-kdrive-ati = "X serv
 DESCRIPTION_xserver-kdrive-sdl = "X server from freedesktop.org, SDL version"
 DESCRIPTION_xserver-kdrive-w100 = "X server from freedesktop.org, supporting the ATI imageon w100 chipset"
 DESCRIPTION_xserver-kdrive-ati = "X server from freedesktop.org, supporting ATI devices"
+DESCRIPTION_xserver-kdrive-glamo = "X server from freedesktop.org, supporting Smedia Glamo chipset"
 DESCRIPTION_xserver-kdrive-chips = "X server from freedesktop.org, supporting Chips chipsets"
 DESCRIPTION_xserver-kdrive-i810 = "X server from freedesktop.org, supporting Intel chipsets"
 DESCRIPTION_xserver-kdrive-imageon = "X server from freedesktop.org, supporting the ATI imageon 100 chipset"
@@ -54,6 +56,7 @@ FILES_xserver-kdrive-ati = "${bindir}/Xa
 FILES_xserver-kdrive-sdl = "${bindir}/Xsdl"
 FILES_xserver-kdrive-w100 = "${bindir}/Xw100"
 FILES_xserver-kdrive-ati = "${bindir}/Xati"
+FILES_xserver-kdrive-glamo = "${bindir}/Xglamo"
 FILES_xserver-kdrive-chips = "${bindir}/Xchips"
 FILES_xserver-kdrive-i810 = "${bindir}/Xi810"
 FILES_xserver-kdrive-imageon = "${bindir}/Ximageon"
@@ -74,6 +77,7 @@ RDEPENDS_xserver-kdrive-ati = "${PN}"
 RDEPENDS_xserver-kdrive-sdl = "${PN}"
 RDEPENDS_xserver-kdrive-w100 = "${PN}"
 RDEPENDS_xserver-kdrive-ati = "${PN}"
+RDEPENDS_xserver-kdrive-glamo = "${PN}"
 RDEPENDS_xserver-kdrive-chips = "${PN}"
 RDEPENDS_xserver-kdrive-i810 = "${PN}"
 RDEPENDS_xserver-kdrive-mach64 = "${PN}"
============================================================
--- packages/xorg-xserver/xserver-kdrive_1.3.0.0.bb	bc48ac913bf5619e2ef613e1dcc2f78c81bcd221
+++ packages/xorg-xserver/xserver-kdrive_1.3.0.0.bb	de61c2062ad218eabe75d458171196d03d0f9181
@@ -21,6 +21,8 @@ SRC_URI = "${XORG_MIRROR}/individual/xse
 	file://w100-fix-offscreen-bmp.patch;patch=1 \
         file://kdrive-1.3-18bpp.patch;patch=1 \
         file://gumstix-kmode.patch;patch=1 \
+        file://smedia-glamo.patch;patch=1 \
+        file://build-glamo.patch;patch=1 \
 "
 
 S = "${WORKDIR}/xorg-server-${PV}"
