 drivers/input/touchscreen/Kconfig       |   43 +
 drivers/input/touchscreen/Makefile      |   17 +
 drivers/input/touchscreen/wm9705.c      |  360 ++++
 drivers/input/touchscreen/wm9712.c      |  464 ++++
 drivers/input/touchscreen/wm9713.c      |  461 ++++
 drivers/input/touchscreen/wm97xx-core.c | 1035 +++++++++
 drivers/video/geode/Kconfig             |   24 +
 drivers/video/geode/Makefile            |    7 +
 drivers/video/geode/build_num.h         |   36 +
 drivers/video/geode/geodefb.c           |  284 +++
 drivers/video/geode/geodefb.h           |   34 +
 drivers/video/geode/geodefb_hw.c        |  105 +
 drivers/video/geode/geodefb_lx.c        |  804 +++++++
 drivers/video/geode/geodefb_lx.h        |   60 +
 drivers/video/geode/geodefb_lx_accel.c  |  168 ++
 drivers/video/geode/geodefb_modes.c     |  110 +
 include/linux/wm97xx.h                  |  294 +++
 lib/Kconfig                             |   10 +
 lib/Makefile                            |    1 +
 lib/cimarron/Makefile                   |    5 +
 lib/cimarron/build_num.h                |   36 +
 lib/cimarron/cim/cim_defs.h             |  717 ++++++
 lib/cimarron/cim/cim_df.c               | 2544 ++++++++++++++++++++++
 lib/cimarron/cim/cim_filter.c           |  533 +++++
 lib/cimarron/cim/cim_gp.c               | 3442 +++++++++++++++++++++++++++++
 lib/cimarron/cim/cim_init.c             |  209 ++
 lib/cimarron/cim/cim_modes.c            | 1822 ++++++++++++++++
 lib/cimarron/cim/cim_msr.c              |  379 ++++
 lib/cimarron/cim/cim_parm.h             | 1268 +++++++++++
 lib/cimarron/cim/cim_regs.h             | 1233 +++++++++++
 lib/cimarron/cim/cim_rtns.h             |  338 +++
 lib/cimarron/cim/cim_version.h          |   15 +
 lib/cimarron/cim/cim_vg.c               | 3589 +++++++++++++++++++++++++++++++
 lib/cimarron/cim/cim_vip.c              | 1565 ++++++++++++++
 lib/cimarron/cim/cim_vop.c              |  564 +++++
 lib/cimarron/cim/cimarron.c             |  222 ++
 lib/cimarron/cim_dev.c                  |  101 +
 lib/cimarron/cim_dev.h                  |   57 +
 lib/cimarron/cim_mem.c                  |  414 ++++
 lib/cimarron/cim_mem.h                  |   87 +
 lib/cimarron/cim_mod.c                  |  123 ++
 lib/cimarron/cimapi.c                   |  509 +++++
 sound/Kconfig                           |    2 +-
 43 files changed, 24090 insertions(+), 1 deletions(-)

diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig
index 6b46c9b..e6ac6b9 100644
--- a/drivers/input/touchscreen/Kconfig
+++ b/drivers/input/touchscreen/Kconfig
@@ -159,4 +159,47 @@ config TOUCHSCREEN_UCB1400
 	  To compile this driver as a module, choose M here: the
 	  module will be called ucb1400_ts.
 
+
+config TOUCHSCREEN_WM97XX
+	tristate "Support for WM97xx AC97 touchscreen controllers"
+	depends AC97_BUS
+
+choice
+	prompt "WM97xx codec type"
+
+config TOUCHSCREEN_WM9705
+	bool "WM9705 Touchscreen interface support"
+	depends on TOUCHSCREEN_WM97XX
+	help
+	  Say Y here if you have the wm9705 touchscreen.
+
+	  If unsure, say N.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called wm9705.
+
+config TOUCHSCREEN_WM9712
+	bool "WM9712 Touchscreen interface support"
+	depends on TOUCHSCREEN_WM97XX
+	help
+	  Say Y here if you have the wm9712 touchscreen.
+
+	  If unsure, say N.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called wm9712.
+
+config TOUCHSCREEN_WM9713
+	bool "WM9713 Touchscreen interface support"
+	depends on TOUCHSCREEN_WM97XX
+	help
+	  Say Y here if you have the wm9713 touchscreen.
+
+	  If unsure, say N.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called wm9713.
+
+endchoice
+
 endif
diff --git a/drivers/input/touchscreen/Makefile b/drivers/input/touchscreen/Makefile
index 30e6e22..543f9b5 100644
--- a/drivers/input/touchscreen/Makefile
+++ b/drivers/input/touchscreen/Makefile
@@ -4,6 +4,8 @@
 
 # Each configuration option enables a list of files.
 
+wm97xx-ts-objs := wm97xx-core.o
+
 obj-$(CONFIG_TOUCHSCREEN_ADS7846)	+= ads7846.o
 obj-$(CONFIG_TOUCHSCREEN_BITSY)	+= h3600_ts_input.o
 obj-$(CONFIG_TOUCHSCREEN_CORGI)	+= corgi_ts.o
@@ -16,3 +18,18 @@ obj-$(CONFIG_TOUCHSCREEN_PENMOUNT)	+= penmount.o
 obj-$(CONFIG_TOUCHSCREEN_TOUCHRIGHT)	+= touchright.o
 obj-$(CONFIG_TOUCHSCREEN_TOUCHWIN)	+= touchwin.o
 obj-$(CONFIG_TOUCHSCREEN_UCB1400)	+= ucb1400_ts.o
+
+obj-$(CONFIG_TOUCHSCREEN_WM97XX)    += wm97xx-ts.o
+obj-$(CONFIG_TOUCHSCREEN_WM97XX_PXA)    += pxa-wm97xx.o
+
+ifeq ($(CONFIG_TOUCHSCREEN_WM9713),y)
+wm97xx-ts-objs += wm9713.o
+endif
+
+ifeq ($(CONFIG_TOUCHSCREEN_WM9712),y)
+wm97xx-ts-objs += wm9712.o
+endif
+
+ifeq ($(CONFIG_TOUCHSCREEN_WM9705),y)
+wm97xx-ts-objs += wm9705.o
+endif
diff --git a/drivers/input/touchscreen/wm9705.c b/drivers/input/touchscreen/wm9705.c
new file mode 100644
index 0000000..1dae63d
--- /dev/null
+++ b/drivers/input/touchscreen/wm9705.c
@@ -0,0 +1,360 @@
+/*
+ * wm9705.c  --  Codec driver for Wolfson WM9705 AC97 Codec.
+ *
+ * Copyright 2003, 2004, 2005, 2006 Wolfson Microelectronics PLC.
+ * Author: Liam Girdwood
+ *         liam.girdwood@wolfsonmicro.com or linux@wolfsonmicro.com
+ * Parts Copyright : Ian Molton <spyro@f2s.com>
+ *                   Andrew Zabolotny <zap@homelink.ru>
+ *                   Russell King <rmk@arm.linux.org.uk>
+ *
+ *  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.
+ *
+ *  Revision history
+ *     6th Sep 2006  Mike Arthur <linux@wolfsonmicro.com>
+ *                   Added pre and post sample calls.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/version.h>
+#include <linux/kernel.h>
+#include <linux/input.h>
+#include <linux/delay.h>
+#include <linux/bitops.h>
+#include <linux/wm97xx.h>
+
+#define TS_NAME			"wm97xx"
+#define WM9705_VERSION		"0.62"
+#define DEFAULT_PRESSURE	0xb0c0
+
+/*
+ * Debug
+ */
+#if 0
+#define dbg(format, arg...) printk(KERN_DEBUG TS_NAME ": " format "\n" , ## arg)
+#else
+#define dbg(format, arg...)
+#endif
+#define err(format, arg...) printk(KERN_ERR TS_NAME ": " format "\n" , ## arg)
+#define info(format, arg...) printk(KERN_INFO TS_NAME ": " format "\n" , ## arg)
+#define warn(format, arg...) printk(KERN_WARNING TS_NAME ": " format "\n" , ## arg)
+
+/*
+ * Module parameters
+ */
+
+/*
+ * Set current used for pressure measurement.
+ *
+ * Set pil = 2 to use 400uA
+ *     pil = 1 to use 200uA and
+ *     pil = 0 to disable pressure measurement.
+ *
+ * This is used to increase the range of values returned by the adc
+ * when measureing touchpanel pressure.
+ */
+static int pil = 0;
+module_param(pil, int, 0);
+MODULE_PARM_DESC(pil, "Set current used for pressure measurement.");
+
+/*
+ * Set threshold for pressure measurement.
+ *
+ * Pen down pressure below threshold is ignored.
+ */
+static int pressure = DEFAULT_PRESSURE & 0xfff;
+module_param(pressure, int, 0);
+MODULE_PARM_DESC(pressure, "Set threshold for pressure measurement.");
+
+/*
+ * Set adc sample delay.
+ *
+ * For accurate touchpanel measurements, some settling time may be
+ * required between the switch matrix applying a voltage across the
+ * touchpanel plate and the ADC sampling the signal.
+ *
+ * This delay can be set by setting delay = n, where n is the array
+ * position of the delay in the array delay_table below.
+ * Long delays > 1ms are supported for completeness, but are not
+ * recommended.
+ */
+static int delay = 4;
+module_param(delay, int, 0);
+MODULE_PARM_DESC(delay, "Set adc sample delay.");
+
+/*
+ * Pen detect comparator threshold.
+ *
+ * 0 to Vmid in 15 steps, 0 = use zero power comparator with Vmid threshold
+ * i.e. 1 =  Vmid/15 threshold
+ *      15 =  Vmid/1 threshold
+ *
+ * Adjust this value if you are having problems with pen detect not
+ * detecting any down events.
+ */
+static int pdd = 8;
+module_param(pdd, int, 0);
+MODULE_PARM_DESC(pdd, "Set pen detect comparator threshold");
+
+/*
+ * Set adc mask function.
+ *
+ * Sources of glitch noise, such as signals driving an LCD display, may feed
+ * through to the touch screen plates and affect measurement accuracy. In
+ * order to minimise this, a signal may be applied to the MASK pin to delay or
+ * synchronise the sampling.
+ *
+ * 0 = No delay or sync
+ * 1 = High on pin stops conversions
+ * 2 = Edge triggered, edge on pin delays conversion by delay param (above)
+ * 3 = Edge triggered, edge on pin starts conversion after delay param
+ */
+static int mask = 0;
+module_param(mask, int, 0);
+MODULE_PARM_DESC(mask, "Set adc mask function.");
+
+/*
+ * ADC sample delay times in uS
+ */
+static const int delay_table[] = {
+	21,    // 1 AC97 Link frames
+	42,    // 2
+	84,    // 4
+	167,   // 8
+	333,   // 16
+	667,   // 32
+	1000,  // 48
+	1333,  // 64
+	2000,  // 96
+	2667,  // 128
+	3333,  // 160
+	4000,  // 192
+	4667,  // 224
+	5333,  // 256
+	6000,  // 288
+	0      // No delay, switch matrix always on
+};
+
+/*
+ * Delay after issuing a POLL command.
+ *
+ * The delay is 3 AC97 link frames + the touchpanel settling delay
+ */
+static inline void poll_delay(int d)
+{
+	udelay (3 * AC97_LINK_FRAME + delay_table [d]);
+}
+
+/*
+ * set up the physical settings of the WM9705
+ */
+static void init_wm9705_phy(struct wm97xx* wm)
+{
+	u16 dig1 = 0, dig2 = WM97XX_RPR;
+
+	/*
+	* mute VIDEO and AUX as they share X and Y touchscreen
+	* inputs on the WM9705
+	*/
+	wm97xx_reg_write(wm, AC97_AUX, 0x8000);
+	wm97xx_reg_write(wm, AC97_VIDEO, 0x8000);
+
+	/* touchpanel pressure current*/
+	if  (pil == 2) {
+		dig2 |= WM9705_PIL;
+		dbg("setting pressure measurement current to 400uA.");
+	} else if (pil)
+		dbg("setting pressure measurement current to 200uA.");
+	if(!pil)
+		pressure = 0;
+
+	/* polling mode sample settling delay */
+	if (delay!=4) {
+		if (delay < 0 || delay > 15) {
+		    dbg("supplied delay out of range.");
+		    delay = 4;
+		}
+	}
+	dig1 &= 0xff0f;
+	dig1 |= WM97XX_DELAY(delay);
+	dbg("setting adc sample delay to %d u Secs.", delay_table[delay]);
+
+	/* WM9705 pdd */
+	dig2 |= (pdd & 0x000f);
+	dbg("setting pdd to Vmid/%d", 1 - (pdd & 0x000f));
+
+	/* mask */
+	dig2 |= ((mask & 0x3) << 4);
+
+	wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER1, dig1);
+	wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER2, dig2);
+}
+
+static int wm9705_digitiser_ioctl(struct wm97xx* wm, int cmd)
+{
+	switch(cmd) {
+	case WM97XX_DIG_START:
+		wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER2, wm->dig[2] | WM97XX_PRP_DET_DIG);
+		wm97xx_reg_read(wm, AC97_WM97XX_DIGITISER_RD); /* dummy read */
+		break;
+	case WM97XX_DIG_STOP:
+		wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER2, wm->dig[2] & ~WM97XX_PRP_DET_DIG);
+		break;
+	case WM97XX_AUX_PREPARE:
+		memcpy(wm->dig_save, wm->dig, sizeof(wm->dig));
+		wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER1, 0);
+		wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER2, WM97XX_PRP_DET_DIG);
+		break;
+	case WM97XX_DIG_RESTORE:
+		wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER1, wm->dig_save[1]);
+		wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER2, wm->dig_save[2]);
+		break;
+	case WM97XX_PHY_INIT:
+		init_wm9705_phy(wm);
+		break;
+	default:
+		return -EINVAL;
+	}
+	return 0;
+}
+
+static inline int is_pden (struct wm97xx* wm)
+{
+	return wm->dig[2] & WM9705_PDEN;
+}
+
+/*
+ * Read a sample from the WM9705 adc in polling mode.
+ */
+static int wm9705_poll_sample (struct wm97xx* wm, int adcsel, int *sample)
+{
+	int timeout = 5 * delay;
+
+	if (!wm->pen_probably_down) {
+		u16 data = wm97xx_reg_read(wm, AC97_WM97XX_DIGITISER_RD);
+		if (!(data & WM97XX_PEN_DOWN))
+			return RC_PENUP;
+		wm->pen_probably_down = 1;
+	}
+
+	/* set up digitiser */
+	if (adcsel & 0x8000)
+		adcsel = ((adcsel & 0x7fff) + 3) << 12;
+
+	if (wm->mach_ops && wm->mach_ops->pre_sample)
+		wm->mach_ops->pre_sample(adcsel);
+	wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER1, adcsel | WM97XX_POLL | WM97XX_DELAY(delay));
+
+	/* wait 3 AC97 time slots + delay for conversion */
+	poll_delay (delay);
+
+	/* wait for POLL to go low */
+	while ((wm97xx_reg_read(wm, AC97_WM97XX_DIGITISER1) & WM97XX_POLL) && timeout) {
+		udelay(AC97_LINK_FRAME);
+		timeout--;
+	}
+
+	if (timeout <= 0) {
+		/* If PDEN is set, we can get a timeout when pen goes up */
+		if (is_pden(wm))
+			wm->pen_probably_down = 0;
+		else
+			dbg ("adc sample timeout");
+		return RC_PENUP;
+	}
+
+	*sample = wm97xx_reg_read(wm, AC97_WM97XX_DIGITISER_RD);
+	if (wm->mach_ops && wm->mach_ops->post_sample)
+		wm->mach_ops->post_sample(adcsel);
+
+	/* check we have correct sample */
+	if ((*sample & WM97XX_ADCSEL_MASK) != adcsel) {
+		dbg ("adc wrong sample, read %x got %x", adcsel,
+		*sample & WM97XX_ADCSEL_MASK);
+		return RC_PENUP;
+	}
+
+	if (!(*sample & WM97XX_PEN_DOWN)) {
+		wm->pen_probably_down = 0;
+		return RC_PENUP;
+	}
+
+	return RC_VALID;
+}
+
+/*
+ * Sample the WM9705 touchscreen in polling mode
+ */
+static int wm9705_poll_touch(struct wm97xx* wm, struct wm97xx_data *data)
+{
+	int rc;
+
+	if ((rc = wm9705_poll_sample(wm, WM97XX_ADCSEL_X, &data->x)) != RC_VALID)
+		return rc;
+	if ((rc = wm9705_poll_sample(wm, WM97XX_ADCSEL_Y, &data->y)) != RC_VALID)
+		return rc;
+	if (pil) {
+		if ((rc = wm9705_poll_sample(wm, WM97XX_ADCSEL_PRES, &data->p)) != RC_VALID)
+			return rc;
+	} else
+		data->p = DEFAULT_PRESSURE;
+
+	return RC_VALID;
+}
+
+/*
+ * Enable WM9705 continuous mode, i.e. touch data is streamed across an AC97 slot
+ */
+static int wm9705_acc_enable (struct wm97xx* wm, int enable)
+{
+	u16 dig1, dig2;
+	int ret = 0;
+
+	dig1 = wm->dig[1];
+	dig2 = wm->dig[2];
+
+	if (enable) {
+		/* continous mode */
+		if (wm->mach_ops->acc_startup && (ret = wm->mach_ops->acc_startup(wm)) < 0)
+			return ret;
+		dig1 &= ~(WM97XX_CM_RATE_MASK | WM97XX_ADCSEL_MASK |
+			WM97XX_DELAY_MASK | WM97XX_SLT_MASK);
+		dig1 |= WM97XX_CTC | WM97XX_COO | WM97XX_SLEN |
+			WM97XX_DELAY (delay) |
+			WM97XX_SLT (wm->acc_slot) |
+			WM97XX_RATE (wm->acc_rate);
+		if (pil)
+			dig1 |= WM97XX_ADCSEL_PRES;
+		dig2 |= WM9705_PDEN;
+	} else {
+		dig1 &= ~(WM97XX_CTC | WM97XX_COO | WM97XX_SLEN);
+		dig2 &= ~WM9705_PDEN;
+		if (wm->mach_ops->acc_shutdown)
+			wm->mach_ops->acc_shutdown(wm);
+	}
+
+	wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER1, dig1);
+	wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER2, dig2);
+	return ret;
+}
+
+struct wm97xx_codec_drv wm97xx_codec = {
+	.id = 	WM9705_ID2,
+	.name = "wm9705",
+	.poll_sample = wm9705_poll_sample,
+	.poll_touch = wm9705_poll_touch,
+	.acc_enable = wm9705_acc_enable,
+	.digitiser_ioctl = wm9705_digitiser_ioctl,
+};
+
+EXPORT_SYMBOL_GPL(wm97xx_codec);
+
+/* Module information */
+MODULE_AUTHOR("Liam Girdwood, liam.girdwood@wolfsonmicro.com, www.wolfsonmicro.com");
+MODULE_DESCRIPTION("WM9705 Touch Screen Driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/input/touchscreen/wm9712.c b/drivers/input/touchscreen/wm9712.c
new file mode 100644
index 0000000..99433e9
--- /dev/null
+++ b/drivers/input/touchscreen/wm9712.c
@@ -0,0 +1,464 @@
+/*
+ * wm9712.c  --  Codec driver for Wolfson WM9712 AC97 Codecs.
+ *
+ * Copyright 2003, 2004, 2005, 2006 Wolfson Microelectronics PLC.
+ * Author: Liam Girdwood
+ *         liam.girdwood@wolfsonmicro.com or linux@wolfsonmicro.com
+ * Parts Copyright : Ian Molton <spyro@f2s.com>
+ *                   Andrew Zabolotny <zap@homelink.ru>
+ *                   Russell King <rmk@arm.linux.org.uk>
+ *
+ *  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.
+ *
+ *  Revision history
+ *     4th Jul 2005  Initial version.
+ *     6th Sep 2006  Mike Arthur <linux@wolfsonmicro.com>
+ *                   Added pre and post sample calls.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/version.h>
+#include <linux/kernel.h>
+#include <linux/input.h>
+#include <linux/delay.h>
+#include <linux/bitops.h>
+#include <linux/wm97xx.h>
+
+#define TS_NAME			"wm97xx"
+#define WM9712_VERSION		"0.61"
+#define DEFAULT_PRESSURE	0xb0c0
+
+/*
+ * Debug
+ */
+#if 0
+#define dbg(format, arg...) printk(KERN_DEBUG TS_NAME ": " format "\n" , ## arg)
+#else
+#define dbg(format, arg...)
+#endif
+#define err(format, arg...) printk(KERN_ERR TS_NAME ": " format "\n" , ## arg)
+#define info(format, arg...) printk(KERN_INFO TS_NAME ": " format "\n" , ## arg)
+#define warn(format, arg...) printk(KERN_WARNING TS_NAME ": " format "\n" , ## arg)
+
+/*
+ * Module parameters
+ */
+
+/*
+ * Set internal pull up for pen detect.
+ *
+ * Pull up is in the range 1.02k (least sensitive) to 64k (most sensitive)
+ * i.e. pull up resistance = 64k Ohms / rpu.
+ *
+ * Adjust this value if you are having problems with pen detect not
+ * detecting any down event.
+ */
+static int rpu = 8;
+module_param(rpu, int, 0);
+MODULE_PARM_DESC(rpu, "Set internal pull up resitor for pen detect.");
+
+/*
+ * Set current used for pressure measurement.
+ *
+ * Set pil = 2 to use 400uA
+ *     pil = 1 to use 200uA and
+ *     pil = 0 to disable pressure measurement.
+ *
+ * This is used to increase the range of values returned by the adc
+ * when measureing touchpanel pressure.
+ */
+static int pil = 0;
+module_param(pil, int, 0);
+MODULE_PARM_DESC(pil, "Set current used for pressure measurement.");
+
+/*
+ * Set threshold for pressure measurement.
+ *
+ * Pen down pressure below threshold is ignored.
+ */
+static int pressure = DEFAULT_PRESSURE & 0xfff;
+module_param(pressure, int, 0);
+MODULE_PARM_DESC(pressure, "Set threshold for pressure measurement.");
+
+/*
+ * Set adc sample delay.
+ *
+ * For accurate touchpanel measurements, some settling time may be
+ * required between the switch matrix applying a voltage across the
+ * touchpanel plate and the ADC sampling the signal.
+ *
+ * This delay can be set by setting delay = n, where n is the array
+ * position of the delay in the array delay_table below.
+ * Long delays > 1ms are supported for completeness, but are not
+ * recommended.
+ */
+static int delay = 3;
+module_param(delay, int, 0);
+MODULE_PARM_DESC(delay, "Set adc sample delay.");
+
+/*
+ * Set five_wire = 1 to use a 5 wire touchscreen.
+ *
+ * NOTE: Five wire mode does not allow for readback of pressure.
+ */
+static int five_wire;
+module_param(five_wire, int, 0);
+MODULE_PARM_DESC(five_wire, "Set to '1' to use 5-wire touchscreen.");
+
+/*
+ * Set adc mask function.
+ *
+ * Sources of glitch noise, such as signals driving an LCD display, may feed
+ * through to the touch screen plates and affect measurement accuracy. In
+ * order to minimise this, a signal may be applied to the MASK pin to delay or
+ * synchronise the sampling.
+ *
+ * 0 = No delay or sync
+ * 1 = High on pin stops conversions
+ * 2 = Edge triggered, edge on pin delays conversion by delay param (above)
+ * 3 = Edge triggered, edge on pin starts conversion after delay param
+ */
+static int mask = 0;
+module_param(mask, int, 0);
+MODULE_PARM_DESC(mask, "Set adc mask function.");
+
+/*
+ * Coordinate Polling Enable.
+ *
+ * Set to 1 to enable coordinate polling. e.g. x,y[,p] is sampled together
+ * for every poll.
+ */
+static int coord = 0;
+module_param(coord, int, 0);
+MODULE_PARM_DESC(coord, "Polling coordinate mode");
+
+/*
+ * ADC sample delay times in uS
+ */
+static const int delay_table[] = {
+	21,    // 1 AC97 Link frames
+	42,    // 2
+	84,    // 4
+	167,   // 8
+	333,   // 16
+	667,   // 32
+	1000,  // 48
+	1333,  // 64
+	2000,  // 96
+	2667,  // 128
+	3333,  // 160
+	4000,  // 192
+	4667,  // 224
+	5333,  // 256
+	6000,  // 288
+	0      // No delay, switch matrix always on
+};
+
+/*
+ * Delay after issuing a POLL command.
+ *
+ * The delay is 3 AC97 link frames + the touchpanel settling delay
+ */
+static inline void poll_delay(int d)
+{
+	udelay (3 * AC97_LINK_FRAME + delay_table [d]);
+}
+
+/*
+ * set up the physical settings of the WM9712
+ */
+static void init_wm9712_phy(struct wm97xx* wm)
+{
+	u16 dig1 = 0;
+	u16 dig2 = WM97XX_RPR | WM9712_RPU(1);
+
+	/* WM9712 rpu */
+	if (rpu) {
+		dig2 &= 0xffc0;
+		dig2 |= WM9712_RPU(rpu);
+		dbg("setting pen detect pull-up to %d Ohms",64000 / rpu);
+	}
+
+	/* touchpanel pressure current*/
+	if (pil == 2) {
+		dig2 |= WM9712_PIL;
+		dbg("setting pressure measurement current to 400uA.");
+	} else if (pil)
+		dbg("setting pressure measurement current to 200uA.");
+	if(!pil)
+		pressure = 0;
+
+	/* WM9712 five wire */
+	if (five_wire) {
+		dig2 |= WM9712_45W;
+		dbg("setting 5-wire touchscreen mode.");
+	}
+
+	/* polling mode sample settling delay */
+	if (delay < 0 || delay > 15) {
+		dbg("supplied delay out of range.");
+		delay = 4;
+	}
+	dig1 &= 0xff0f;
+	dig1 |= WM97XX_DELAY(delay);
+	dbg("setting adc sample delay to %d u Secs.", delay_table[delay]);
+
+	/* mask */
+	dig2 |= ((mask & 0x3) << 6);
+	if (mask) {
+		u16 reg;
+		/* Set GPIO4 as Mask Pin*/
+		reg = wm97xx_reg_read(wm, AC97_MISC_AFE);
+		wm97xx_reg_write(wm, AC97_MISC_AFE, reg | WM97XX_GPIO_4);
+		reg = wm97xx_reg_read(wm, AC97_GPIO_CFG);
+		wm97xx_reg_write(wm, AC97_GPIO_CFG, reg | WM97XX_GPIO_4);
+	}
+
+	/* wait - coord mode */
+	if(coord)
+		dig2 |= WM9712_WAIT;
+
+	wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER1, dig1);
+	wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER2, dig2);
+}
+
+static int wm9712_digitiser_ioctl(struct wm97xx* wm, int cmd)
+{
+	u16 dig2 = wm->dig[2];
+
+	switch(cmd) {
+	case WM97XX_DIG_START:
+		wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER2, dig2 | WM97XX_PRP_DET_DIG);
+		wm97xx_reg_read(wm, AC97_WM97XX_DIGITISER_RD); /* dummy read */
+		break;
+	case WM97XX_DIG_STOP:
+		wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER2, dig2 & ~WM97XX_PRP_DET_DIG);
+		break;
+	case WM97XX_AUX_PREPARE:
+		memcpy(wm->dig_save, wm->dig, sizeof(wm->dig));
+		wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER1, 0);
+		wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER2, WM97XX_PRP_DET_DIG);
+		break;
+	case WM97XX_DIG_RESTORE:
+		wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER1, wm->dig_save[1]);
+		wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER2, wm->dig_save[2]);
+		break;
+	case WM97XX_PHY_INIT:
+		init_wm9712_phy(wm);
+		break;
+	default:
+		return -EINVAL;
+	}
+	return 0;
+}
+
+static inline int is_pden (struct wm97xx* wm)
+{
+	return wm->dig[2] & WM9712_PDEN;
+}
+
+/*
+ * Read a sample from the WM9712 adc in polling mode.
+ */
+static int wm9712_poll_sample (struct wm97xx* wm, int adcsel, int *sample)
+{
+	int timeout = 5 * delay;
+
+	if (!wm->pen_probably_down) {
+		u16 data = wm97xx_reg_read(wm, AC97_WM97XX_DIGITISER_RD);
+		if (!(data & WM97XX_PEN_DOWN))
+			return RC_PENUP;
+		wm->pen_probably_down = 1;
+	}
+
+	/* set up digitiser */
+	if (adcsel & 0x8000)
+		adcsel = ((adcsel & 0x7fff) + 3) << 12;
+
+	if (wm->mach_ops && wm->mach_ops->pre_sample)
+		wm->mach_ops->pre_sample(adcsel);
+	wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER1, adcsel | WM97XX_POLL | WM97XX_DELAY(delay));
+
+	/* wait 3 AC97 time slots + delay for conversion */
+	poll_delay (delay);
+
+	/* wait for POLL to go low */
+	while ((wm97xx_reg_read(wm, AC97_WM97XX_DIGITISER1) & WM97XX_POLL) && timeout) {
+		udelay(AC97_LINK_FRAME);
+		timeout--;
+	}
+
+	if (timeout <= 0) {
+		/* If PDEN is set, we can get a timeout when pen goes up */
+		if (is_pden(wm))
+			wm->pen_probably_down = 0;
+		else
+			dbg ("adc sample timeout");
+		return RC_PENUP;
+	}
+
+	*sample = wm97xx_reg_read(wm, AC97_WM97XX_DIGITISER_RD);
+	if (wm->mach_ops && wm->mach_ops->post_sample)
+		wm->mach_ops->post_sample(adcsel);
+
+	/* check we have correct sample */
+	if ((*sample & WM97XX_ADCSEL_MASK) != adcsel) {
+		dbg ("adc wrong sample, read %x got %x", adcsel,
+		*sample & WM97XX_ADCSEL_MASK);
+		return RC_PENUP;
+	}
+
+	if (!(*sample & WM97XX_PEN_DOWN)) {
+		wm->pen_probably_down = 0;
+		return RC_PENUP;
+	}
+
+	return RC_VALID;
+}
+
+/*
+ * Read a coord from the WM9712 adc in polling mode.
+ */
+static int wm9712_poll_coord (struct wm97xx* wm, struct wm97xx_data *data)
+{
+	int timeout = 5 * delay;
+
+	if (!wm->pen_probably_down) {
+		u16 data = wm97xx_reg_read(wm, AC97_WM97XX_DIGITISER_RD);
+		if (!(data & WM97XX_PEN_DOWN))
+			return RC_PENUP;
+		wm->pen_probably_down = 1;
+	}
+
+	/* set up digitiser */
+	if (wm->mach_ops && wm->mach_ops->pre_sample)
+		wm->mach_ops->pre_sample(WM97XX_ADCSEL_X | WM97XX_ADCSEL_Y);
+
+	wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER1,
+		WM97XX_COO | WM97XX_POLL | WM97XX_DELAY(delay));
+
+	/* wait 3 AC97 time slots + delay for conversion and read x */
+	poll_delay(delay);
+	data->x = wm97xx_reg_read(wm, AC97_WM97XX_DIGITISER_RD);
+	/* wait for POLL to go low */
+	while ((wm97xx_reg_read(wm, AC97_WM97XX_DIGITISER1) & WM97XX_POLL) && timeout) {
+		udelay(AC97_LINK_FRAME);
+		timeout--;
+	}
+
+	if (timeout <= 0) {
+		/* If PDEN is set, we can get a timeout when pen goes up */
+		if (is_pden(wm))
+			wm->pen_probably_down = 0;
+		else
+			dbg ("adc sample timeout");
+		return RC_PENUP;
+	}
+
+	/* read back y data */
+	data->y = wm97xx_reg_read(wm, AC97_WM97XX_DIGITISER_RD);
+	if (pil)
+		data->p = wm97xx_reg_read(wm, AC97_WM97XX_DIGITISER_RD);
+	else
+		data->p = DEFAULT_PRESSURE;
+
+	if (wm->mach_ops && wm->mach_ops->post_sample)
+		wm->mach_ops->post_sample(WM97XX_ADCSEL_X | WM97XX_ADCSEL_Y);
+
+	/* check we have correct sample */
+	if (!(data->x & WM97XX_ADCSEL_X) || !(data->y & WM97XX_ADCSEL_Y))
+		goto err;
+	if(pil && !(data->p & WM97XX_ADCSEL_PRES))
+		goto err;
+
+	if (!(data->x & WM97XX_PEN_DOWN)) {
+		wm->pen_probably_down = 0;
+		return RC_PENUP;
+	}
+	return RC_VALID;
+err:
+	return RC_PENUP;
+}
+
+/*
+ * Sample the WM9712 touchscreen in polling mode
+ */
+static int wm9712_poll_touch(struct wm97xx* wm, struct wm97xx_data *data)
+{
+	int rc;
+
+	if(coord) {
+		if((rc = wm9712_poll_coord(wm, data)) != RC_VALID)
+			return rc;
+	} else {
+		if ((rc = wm9712_poll_sample(wm, WM97XX_ADCSEL_X, &data->x)) != RC_VALID)
+			return rc;
+
+		if ((rc = wm9712_poll_sample(wm, WM97XX_ADCSEL_Y, &data->y)) != RC_VALID)
+			return rc;
+
+		if (pil && !five_wire) {
+			if ((rc = wm9712_poll_sample(wm, WM97XX_ADCSEL_PRES, &data->p)) != RC_VALID)
+				return rc;
+		} else
+			data->p = DEFAULT_PRESSURE;
+	}
+	return RC_VALID;
+}
+
+/*
+ * Enable WM9712 continuous mode, i.e. touch data is streamed across an AC97 slot
+ */
+static int wm9712_acc_enable (struct wm97xx* wm, int enable)
+{
+	u16 dig1, dig2;
+	int ret = 0;
+
+	dig1 = wm->dig[1];
+	dig2 = wm->dig[2];
+
+	if (enable) {
+		/* continous mode */
+		if (wm->mach_ops->acc_startup && (ret = wm->mach_ops->acc_startup(wm)) < 0)
+			return ret;
+		dig1 &= ~(WM97XX_CM_RATE_MASK | WM97XX_ADCSEL_MASK |
+			WM97XX_DELAY_MASK | WM97XX_SLT_MASK);
+		dig1 |= WM97XX_CTC | WM97XX_COO | WM97XX_SLEN |
+			WM97XX_DELAY (delay) |
+			WM97XX_SLT (wm->acc_slot) |
+			WM97XX_RATE (wm->acc_rate);
+		if (pil)
+			dig1 |= WM97XX_ADCSEL_PRES;
+		dig2 |= WM9712_PDEN;
+	} else {
+		dig1 &= ~(WM97XX_CTC | WM97XX_COO | WM97XX_SLEN);
+		dig2 &= ~WM9712_PDEN;
+		if (wm->mach_ops->acc_shutdown)
+			wm->mach_ops->acc_shutdown(wm);
+	}
+
+	wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER1, dig1);
+	wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER2, dig2);
+	return 0;
+}
+
+struct wm97xx_codec_drv wm97xx_codec = {
+	.id = 	WM9712_ID2,
+	.name = "wm9712",
+	.poll_sample = wm9712_poll_sample,
+	.poll_touch = wm9712_poll_touch,
+	.acc_enable = wm9712_acc_enable,
+	.digitiser_ioctl = wm9712_digitiser_ioctl,
+};
+
+EXPORT_SYMBOL_GPL(wm97xx_codec);
+
+/* Module information */
+MODULE_AUTHOR("Liam Girdwood, liam.girdwood@wolfsonmicro.com, www.wolfsonmicro.com");
+MODULE_DESCRIPTION("WM9712 Touch Screen Driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/input/touchscreen/wm9713.c b/drivers/input/touchscreen/wm9713.c
new file mode 100644
index 0000000..42f5f30
--- /dev/null
+++ b/drivers/input/touchscreen/wm9713.c
@@ -0,0 +1,461 @@
+/*
+ * wm9713.c  --  Codec touch driver for Wolfson WM9713 AC97 Codec.
+ *
+ * Copyright 2003, 2004, 2005, 2006 Wolfson Microelectronics PLC.
+ * Author: Liam Girdwood
+ *         liam.girdwood@wolfsonmicro.com or linux@wolfsonmicro.com
+ * Parts Copyright : Ian Molton <spyro@f2s.com>
+ *                   Andrew Zabolotny <zap@homelink.ru>
+ *                   Russell King <rmk@arm.linux.org.uk>
+ *
+ *  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.
+ *
+ *  Revision history
+ *     6th Sep 2006  Mike Arthur <linux@wolfsonmicro.com>
+ *                   Added pre and post sample calls.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/version.h>
+#include <linux/kernel.h>
+#include <linux/input.h>
+#include <linux/delay.h>
+#include <linux/bitops.h>
+#include <linux/wm97xx.h>
+
+#define TS_NAME			"wm97xx"
+#define WM9713_VERSION		"0.53"
+#define DEFAULT_PRESSURE	0xb0c0
+
+/*
+ * Debug
+ */
+#if 0
+#define dbg(format, arg...) printk(KERN_DEBUG TS_NAME ": " format "\n" , ## arg)
+#else
+#define dbg(format, arg...)
+#endif
+#define err(format, arg...) printk(KERN_ERR TS_NAME ": " format "\n" , ## arg)
+#define info(format, arg...) printk(KERN_INFO TS_NAME ": " format "\n" , ## arg)
+#define warn(format, arg...) printk(KERN_WARNING TS_NAME ": " format "\n" , ## arg)
+
+/*
+ * Module parameters
+ */
+
+/*
+ * Set internal pull up for pen detect.
+ *
+ * Pull up is in the range 1.02k (least sensitive) to 64k (most sensitive)
+ * i.e. pull up resistance = 64k Ohms / rpu.
+ *
+ * Adjust this value if you are having problems with pen detect not
+ * detecting any down event.
+ */
+static int rpu = 8;
+module_param(rpu, int, 0);
+MODULE_PARM_DESC(rpu, "Set internal pull up resitor for pen detect.");
+
+/*
+ * Set current used for pressure measurement.
+ *
+ * Set pil = 2 to use 400uA
+ *     pil = 1 to use 200uA and
+ *     pil = 0 to disable pressure measurement.
+ *
+ * This is used to increase the range of values returned by the adc
+ * when measureing touchpanel pressure.
+ */
+static int pil = 0;
+module_param(pil, int, 0);
+MODULE_PARM_DESC(pil, "Set current used for pressure measurement.");
+
+/*
+ * Set threshold for pressure measurement.
+ *
+ * Pen down pressure below threshold is ignored.
+ */
+static int pressure = DEFAULT_PRESSURE & 0xfff;
+module_param(pressure, int, 0);
+MODULE_PARM_DESC(pressure, "Set threshold for pressure measurement.");
+
+/*
+ * Set adc sample delay.
+ *
+ * For accurate touchpanel measurements, some settling time may be
+ * required between the switch matrix applying a voltage across the
+ * touchpanel plate and the ADC sampling the signal.
+ *
+ * This delay can be set by setting delay = n, where n is the array
+ * position of the delay in the array delay_table below.
+ * Long delays > 1ms are supported for completeness, but are not
+ * recommended.
+ */
+static int delay = 4;
+module_param(delay, int, 0);
+MODULE_PARM_DESC(delay, "Set adc sample delay.");
+
+/*
+ * Set adc mask function.
+ *
+ * Sources of glitch noise, such as signals driving an LCD display, may feed
+ * through to the touch screen plates and affect measurement accuracy. In
+ * order to minimise this, a signal may be applied to the MASK pin to delay or
+ * synchronise the sampling.
+ *
+ * 0 = No delay or sync
+ * 1 = High on pin stops conversions
+ * 2 = Edge triggered, edge on pin delays conversion by delay param (above)
+ * 3 = Edge triggered, edge on pin starts conversion after delay param
+ */
+static int mask = 0;
+module_param(mask, int, 0);
+MODULE_PARM_DESC(mask, "Set adc mask function.");
+
+/*
+ * Coordinate Polling Enable.
+ *
+ * Set to 1 to enable coordinate polling. e.g. x,y[,p] is sampled together
+ * for every poll.
+ */
+static int coord = 0;
+module_param(coord, int, 0);
+MODULE_PARM_DESC(coord, "Polling coordinate mode");
+
+/*
+ * ADC sample delay times in uS
+ */
+static const int delay_table[] = {
+	21,    // 1 AC97 Link frames
+	42,    // 2
+	84,    // 4
+	167,   // 8
+	333,   // 16
+	667,   // 32
+	1000,  // 48
+	1333,  // 64
+	2000,  // 96
+	2667,  // 128
+	3333,  // 160
+	4000,  // 192
+	4667,  // 224
+	5333,  // 256
+	6000,  // 288
+	0      // No delay, switch matrix always on
+};
+
+/*
+ * Delay after issuing a POLL command.
+ *
+ * The delay is 3 AC97 link frames + the touchpanel settling delay
+ */
+static inline void poll_delay(int d)
+{
+	udelay (3 * AC97_LINK_FRAME + delay_table [d]);
+}
+
+/*
+ * set up the physical settings of the WM9713
+ */
+static void init_wm9713_phy(struct wm97xx* wm)
+{
+	u16 dig1 = 0, dig2, dig3;
+
+	/* default values */
+	dig2 = WM97XX_DELAY(4) | WM97XX_SLT(5);
+	dig3= WM9712_RPU(1);
+
+	/* rpu */
+	if (rpu) {
+		dig3 &= 0xffc0;
+		dig3 |= WM9712_RPU(rpu);
+		info("setting pen detect pull-up to %d Ohms",64000 / rpu);
+	}
+
+	/* touchpanel pressure */
+	if (pil == 2) {
+		dig3 |= WM9712_PIL;
+		info("setting pressure measurement current to 400uA.");
+	} else if (pil)
+		info ("setting pressure measurement current to 200uA.");
+	if(!pil)
+		pressure = 0;
+
+	/* sample settling delay */
+	if (delay < 0 || delay > 15) {
+		info ("supplied delay out of range.");
+		delay = 4;
+		info("setting adc sample delay to %d u Secs.", delay_table[delay]);
+	}
+	dig2 &= 0xff0f;
+	dig2 |= WM97XX_DELAY(delay);
+
+	/* mask */
+	dig3 |= ((mask & 0x3) << 4);
+	if(coord)
+		dig3 |= WM9713_WAIT;
+
+	wm->misc = wm97xx_reg_read(wm, 0x5a);
+
+	wm97xx_reg_write(wm, AC97_WM9713_DIG1, dig1);
+	wm97xx_reg_write(wm, AC97_WM9713_DIG2, dig2);
+	wm97xx_reg_write(wm, AC97_WM9713_DIG3, dig3);
+	wm97xx_reg_write(wm, AC97_GPIO_STICKY, 0x0);
+}
+
+static int wm9713_digitiser_ioctl(struct wm97xx* wm, int cmd)
+{
+	u16 val = 0;
+
+	switch(cmd){
+	case WM97XX_DIG_START:
+		val = wm97xx_reg_read(wm, AC97_EXTENDED_MID);
+		wm97xx_reg_write(wm, AC97_EXTENDED_MID, val & 0x7fff);
+		wm97xx_reg_write(wm, AC97_WM9713_DIG3, wm->dig[2] | WM97XX_PRP_DET_DIG);
+		wm97xx_reg_read(wm, AC97_WM97XX_DIGITISER_RD); /* dummy read */
+		break;
+	case WM97XX_DIG_STOP:
+		wm97xx_reg_write(wm, AC97_WM9713_DIG3, wm->dig[2] & ~WM97XX_PRP_DET_DIG);
+		val = wm97xx_reg_read(wm, AC97_EXTENDED_MID);
+		wm97xx_reg_write(wm, AC97_EXTENDED_MID, val | 0x8000);
+		break;
+	case WM97XX_AUX_PREPARE:
+		memcpy(wm->dig_save, wm->dig, sizeof(wm->dig));
+		wm97xx_reg_write(wm, AC97_WM9713_DIG1, 0);
+		wm97xx_reg_write(wm, AC97_WM9713_DIG2, 0);
+		wm97xx_reg_write(wm, AC97_WM9713_DIG3, WM97XX_PRP_DET_DIG);
+		break;
+	case WM97XX_DIG_RESTORE:
+		wm97xx_reg_write(wm, AC97_WM9713_DIG1, wm->dig_save[0]);
+		wm97xx_reg_write(wm, AC97_WM9713_DIG2, wm->dig_save[1]);
+		wm97xx_reg_write(wm, AC97_WM9713_DIG3, wm->dig_save[2]);
+		break;
+	case WM97XX_PHY_INIT:
+		init_wm9713_phy(wm);
+		break;
+	default:
+		return -EINVAL;
+	}
+	return 0;
+}
+
+static inline int is_pden (struct wm97xx* wm)
+{
+	return wm->dig[2] & WM9713_PDEN;
+}
+
+/*
+ * Read a sample from the WM9713 adc in polling mode.
+ */
+static int wm9713_poll_sample (struct wm97xx* wm, int adcsel, int *sample)
+{
+	u16 dig1;
+	int timeout = 5 * delay;
+
+	if (!wm->pen_probably_down) {
+		u16 data = wm97xx_reg_read(wm, AC97_WM97XX_DIGITISER_RD);
+		if (!(data & WM97XX_PEN_DOWN))
+			return RC_PENUP;
+		wm->pen_probably_down = 1;
+	}
+
+	/* set up digitiser */
+	if (adcsel & 0x8000)
+		adcsel = 1 << ((adcsel & 0x7fff) + 3);
+
+	dig1 = wm97xx_reg_read(wm, AC97_WM9713_DIG1);
+	dig1 &= ~WM9713_ADCSEL_MASK;
+
+	if (wm->mach_ops && wm->mach_ops->pre_sample)
+		wm->mach_ops->pre_sample(adcsel);
+	wm97xx_reg_write(wm, AC97_WM9713_DIG1, dig1 | adcsel |WM9713_POLL);
+
+	/* wait 3 AC97 time slots + delay for conversion */
+	poll_delay(delay);
+
+	/* wait for POLL to go low */
+	while ((wm97xx_reg_read(wm, AC97_WM9713_DIG1) & WM9713_POLL) && timeout) {
+		udelay(AC97_LINK_FRAME);
+		timeout--;
+	}
+
+	if (timeout <= 0) {
+		/* If PDEN is set, we can get a timeout when pen goes up */
+		if (is_pden(wm))
+			wm->pen_probably_down = 0;
+		else
+			dbg ("adc sample timeout");
+		return RC_PENUP;
+	}
+
+	*sample =wm97xx_reg_read(wm, AC97_WM97XX_DIGITISER_RD);
+	if (wm->mach_ops && wm->mach_ops->post_sample)
+		wm->mach_ops->post_sample(adcsel);
+
+	/* check we have correct sample */
+	if ((*sample & WM97XX_ADCSRC_MASK) != ffs(adcsel >> 1) << 12) {
+		dbg ("adc wrong sample, read %x got %x", adcsel,
+		     *sample & WM97XX_ADCSRC_MASK);
+		return RC_PENUP;
+	}
+
+	if (!(*sample & WM97XX_PEN_DOWN)) {
+		wm->pen_probably_down = 0;
+		return RC_PENUP;
+	}
+
+	return RC_VALID;
+}
+
+/*
+ * Read a coordinate from the WM9713 adc in polling mode.
+ */
+static int wm9713_poll_coord (struct wm97xx* wm, struct wm97xx_data *data)
+{
+	u16 dig1;
+	int timeout = 5 * delay;
+
+	if (!wm->pen_probably_down) {
+		u16 data = wm97xx_reg_read(wm, AC97_WM97XX_DIGITISER_RD);
+		if (!(data & WM97XX_PEN_DOWN))
+			return RC_PENUP;
+		wm->pen_probably_down = 1;
+	}
+
+	/* set up digitiser */
+	dig1 = wm97xx_reg_read(wm, AC97_WM9713_DIG1);
+	dig1 &= ~WM9713_ADCSEL_MASK;
+	if(pil)
+		dig1 |= WM97XX_ADCSEL_PRES;
+
+	if (wm->mach_ops && wm->mach_ops->pre_sample)
+		wm->mach_ops->pre_sample(WM97XX_ADCSEL_X | WM97XX_ADCSEL_Y);
+	wm97xx_reg_write(wm, AC97_WM9713_DIG1, dig1 | WM9713_POLL | WM9713_COO);
+
+	/* wait 3 AC97 time slots + delay for conversion */
+	poll_delay(delay);
+	data->x = wm97xx_reg_read(wm, AC97_WM97XX_DIGITISER_RD);
+	/* wait for POLL to go low */
+	while ((wm97xx_reg_read(wm, AC97_WM9713_DIG1) & WM9713_POLL) && timeout) {
+		udelay(AC97_LINK_FRAME);
+		timeout--;
+	}
+
+	if (timeout <= 0) {
+		/* If PDEN is set, we can get a timeout when pen goes up */
+		if (is_pden(wm))
+			wm->pen_probably_down = 0;
+		else
+			dbg ("adc sample timeout");
+		return RC_PENUP;
+	}
+
+	/* read back data */
+	data->y = wm97xx_reg_read(wm, AC97_WM97XX_DIGITISER_RD);
+	if (pil)
+		data->p = wm97xx_reg_read(wm, AC97_WM97XX_DIGITISER_RD);
+	else
+		data->p = DEFAULT_PRESSURE;
+
+	if (wm->mach_ops && wm->mach_ops->post_sample)
+		wm->mach_ops->post_sample(WM97XX_ADCSEL_X | WM97XX_ADCSEL_Y);
+
+	/* check we have correct sample */
+	if (!(data->x & WM97XX_ADCSEL_X) || !(data->y & WM97XX_ADCSEL_Y))
+		goto err;
+	if(pil && !(data->p & WM97XX_ADCSEL_PRES))
+		goto err;
+
+	if (!(data->x & WM97XX_PEN_DOWN)) {
+		wm->pen_probably_down = 0;
+		return RC_PENUP;
+	}
+	return RC_VALID;
+err:
+	return RC_PENUP;
+}
+
+/*
+ * Sample the WM9713 touchscreen in polling mode
+ */
+static int wm9713_poll_touch(struct wm97xx* wm, struct wm97xx_data *data)
+{
+	int rc;
+
+	if(coord) {
+		if((rc = wm9713_poll_coord(wm, data)) != RC_VALID)
+			return rc;
+	} else {
+		if ((rc = wm9713_poll_sample(wm, WM9713_ADCSEL_X, &data->x)) != RC_VALID)
+			return rc;
+		if ((rc = wm9713_poll_sample(wm, WM9713_ADCSEL_Y, &data->y)) != RC_VALID)
+			return rc;
+		if (pil) {
+			if ((rc = wm9713_poll_sample(wm, WM9713_ADCSEL_PRES, &data->p)) != RC_VALID)
+				return rc;
+		} else
+			data->p = DEFAULT_PRESSURE;
+	}
+	return RC_VALID;
+}
+
+/*
+ * Enable WM9713 continuous mode, i.e. touch data is streamed across an AC97 slot
+ */
+static int wm9713_acc_enable (struct wm97xx* wm, int enable)
+{
+	u16 dig1, dig2, dig3;
+	int ret = 0;
+
+	dig1 = wm->dig[0];
+	dig2 = wm->dig[1];
+	dig3 = wm->dig[2];
+
+	if (enable) {
+		/* continous mode */
+		if (wm->mach_ops->acc_startup &&
+			(ret = wm->mach_ops->acc_startup(wm)) < 0)
+			return ret;
+
+		dig1 &= ~WM9713_ADCSEL_MASK;
+		dig1 |= WM9713_CTC | WM9713_COO | WM9713_ADCSEL_X | WM9713_ADCSEL_Y;
+        if (pil)
+		dig1 |= WM9713_ADCSEL_PRES;
+		dig2 &= ~(WM97XX_DELAY_MASK | WM97XX_SLT_MASK  | WM97XX_CM_RATE_MASK);
+		dig2 |= WM97XX_SLEN | WM97XX_DELAY (delay) |
+		WM97XX_SLT (wm->acc_slot) | WM97XX_RATE (wm->acc_rate);
+		dig3 |= WM9713_PDEN;
+	} else {
+		dig1 &= ~(WM9713_CTC | WM9713_COO);
+		dig2 &= ~WM97XX_SLEN;
+		dig3 &= ~WM9713_PDEN;
+        if (wm->mach_ops->acc_shutdown)
+            wm->mach_ops->acc_shutdown(wm);
+	}
+
+	wm97xx_reg_write(wm, AC97_WM9713_DIG1, dig1);
+	wm97xx_reg_write(wm, AC97_WM9713_DIG2, dig2);
+	wm97xx_reg_write(wm, AC97_WM9713_DIG3, dig3);
+	return ret;
+}
+
+struct wm97xx_codec_drv wm97xx_codec = {
+	.id = 	WM9713_ID2,
+    .name = "wm9713",
+	.poll_sample = wm9713_poll_sample,
+	.poll_touch = wm9713_poll_touch,
+	.acc_enable = wm9713_acc_enable,
+	.digitiser_ioctl = wm9713_digitiser_ioctl,
+};
+
+EXPORT_SYMBOL_GPL(wm97xx_codec);
+
+/* Module information */
+MODULE_AUTHOR("Liam Girdwood, liam.girdwood@wolfsonmicro.com, www.wolfsonmicro.com");
+MODULE_DESCRIPTION("WM9713 Touch Screen Driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/input/touchscreen/wm97xx-core.c b/drivers/input/touchscreen/wm97xx-core.c
new file mode 100644
index 0000000..fd80905
--- /dev/null
+++ b/drivers/input/touchscreen/wm97xx-core.c
@@ -0,0 +1,1035 @@
+/*
+ * wm97xx-core.c  --  Touch screen driver core for Wolfson WM9705, WM9712
+ *                    and WM9713 AC97 Codecs.
+ *
+ * Copyright 2003, 2004, 2005, 2006 Wolfson Microelectronics PLC.
+ * Author: Liam Girdwood
+ *         liam.girdwood@wolfsonmicro.com or linux@wolfsonmicro.com
+ * Parts Copyright : Ian Molton <spyro@f2s.com>
+ *                   Andrew Zabolotny <zap@homelink.ru>
+ *                   Russell King <rmk@arm.linux.org.uk>
+ *
+ *  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.
+ *
+ * Notes:
+ *
+ *  Features:
+ *       - supports WM9705, WM9712, WM9713
+ *       - polling mode
+ *       - continuous mode (arch-dependent)
+ *       - adjustable rpu/dpp settings
+ *       - adjustable pressure current
+ *       - adjustable sample settle delay
+ *       - 4 and 5 wire touchscreens (5 wire is WM9712 only)
+ *       - pen down detection
+ *       - battery monitor
+ *       - sample AUX adc's
+ *       - power management
+ *       - codec GPIO
+ *       - codec event notification
+ * Todo
+ *       - Support for async sampling control for noisy LCD's.
+ *
+ *  Revision history
+ *    7th May 2003   Initial version.
+ *    6th June 2003  Added non module support and AC97 registration.
+ *   18th June 2003  Added AUX adc sampling.
+ *   23rd June 2003  Did some minimal reformatting, fixed a couple of
+ *                   codec_mutexing bugs and noted a race to fix.
+ *   24th June 2003  Added power management and fixed race condition.
+ *   10th July 2003  Changed to a misc device.
+ *   31st July 2003  Moved TS_EVENT and TS_CAL to wm97xx.h
+ *    8th Aug  2003  Added option for read() calling wm97xx_sample_touch()
+ *                   because some ac97_read/ac_97_write call schedule()
+ *    7th Nov  2003  Added Input touch event interface, stanley.cai@intel.com
+ *   13th Nov  2003  Removed h3600 touch interface, added interrupt based
+ *                   pen down notification and implemented continous mode
+ *                   on XScale arch.
+ *   16th Nov  2003  Ian Molton <spyro@f2s.com>
+ *                   Modified so that it suits the new 2.6 driver model.
+ *   25th Jan  2004  Andrew Zabolotny <zap@homelink.ru>
+ *                   Implemented IRQ-driven pen down detection, implemented
+ *                   the private API meant to be exposed to platform-specific
+ *                   drivers, reorganized the driver so that it supports
+ *                   an arbitrary number of devices.
+ *    1st Feb  2004  Moved continuous mode handling to a separate
+ *                   architecture-dependent file. For now only PXA
+ *                   built-in AC97 controller is supported (pxa-ac97-wm97xx.c).
+ *    11th Feb 2004  Reduced CPU usage by keeping a cached copy of both
+ *                   digitizer registers instead of reading them every time.
+ *                   A reorganization of the whole code for better
+ *                   error handling.
+ *    17th Apr 2004  Added BMON support.
+ *    17th Nov 2004  Added codec GPIO, codec event handling (real and virtual
+ *                   GPIOs) and 2.6 power management.
+ *    29th Nov 2004  Added WM9713 support.
+ *     4th Jul 2005  Moved codec specific code out to seperate files.
+ *     6th Sep 2006  Mike Arthur <linux@wolfsonmicro.com>
+ *                   Added bus interface.
+ */
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/version.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/string.h>
+#include <linux/proc_fs.h>
+#include <linux/pm.h>
+#include <linux/interrupt.h>
+#include <linux/bitops.h>
+#include <linux/workqueue.h>
+#include <linux/device.h>
+#include <linux/freezer.h>
+#include <linux/wm97xx.h>
+#include <asm/uaccess.h>
+#include <asm/io.h>
+
+#define TS_NAME			"wm97xx"
+#define WM_CORE_VERSION		"0.64"
+#define DEFAULT_PRESSURE	0xb0c0
+
+
+/*
+ * Touchscreen absolute values
+ *
+ * These parameters are used to help the input layer discard out of
+ * range readings and reduce jitter etc.
+ *
+ *   o min, max:- indicate the min and max values your touch screen returns
+ *   o fuzz:- use a higher number to reduce jitter
+ *
+ * The default values correspond to Mainstone II in QVGA mode
+ *
+ * Please read
+ * Documentation/input/input-programming.txt for more details.
+ */
+
+static int abs_x[3] = {350,3900,5};
+module_param_array(abs_x, int, NULL, 0);
+MODULE_PARM_DESC(abs_x, "Touchscreen absolute X min, max, fuzz");
+
+static int abs_y[3] = {320,3750,40};
+module_param_array(abs_y, int, NULL, 0);
+MODULE_PARM_DESC(abs_y, "Touchscreen absolute Y min, max, fuzz");
+
+static int abs_p[3] = {0,150,4};
+module_param_array(abs_p, int, NULL, 0);
+MODULE_PARM_DESC(abs_p, "Touchscreen absolute Pressure min, max, fuzz");
+
+static int dejitter_delta = 50;
+module_param(dejitter_delta, int, 0);
+MODULE_PARM_DESC(dejitter_delta, "Touchscreen dejitter delta");
+
+static int dejitter_history = 8;
+module_param(dejitter_history, int, 0);
+MODULE_PARM_DESC(dejitter_history, "Touchscreen dejitter history");
+
+static int enable_btn = 1;
+module_param(enable_btn, int, 0);
+MODULE_PARM_DESC(enable_btn, "Enable/disbale BUTTON_* events");
+
+/*
+ * Debug
+ */
+#if 0
+#define dbg(format, arg...) printk(KERN_DEBUG TS_NAME ": " format "\n" , ## arg)
+#else
+#define dbg(format, arg...)
+#endif
+#define err(format, arg...) printk(KERN_ERR TS_NAME ": " format "\n" , ## arg)
+#define info(format, arg...) printk(KERN_INFO TS_NAME ": " format "\n" , ## arg)
+#define warn(format, arg...) printk(KERN_WARNING TS_NAME ": " format "\n" , ## arg)
+
+/*
+ * Dejitter module from ts_lib
+ */
+
+/*
+ *  tslib/plugins/dejitter.c
+ *
+ *  Copyright (C) 2001 Russell King.
+ *
+ * This file is placed under the LGPL.  Please see the file
+ * COPYING for more details.
+ *
+ * $Id: dejitter.c,v 1.1.1.1 2005/03/03 17:42:41 qjbian Exp $
+ *
+ * Problem: some touchscreens read the X/Y values from ADC with a
+ * great level of noise in their lowest bits. This produces "jitter"
+ * in touchscreen output, e.g. even if we hold the stylus still,
+ * we get a great deal of X/Y coordinate pairs that are close enough
+ * but not equal. Also if we try to draw a straight line in a painter
+ * program, we'll get a line full of spikes.
+ *
+ * Solution: we apply a smoothing filter on the last several values
+ * thus excluding spikes from output. If we detect a substantial change
+ * in coordinates, we reset the backlog of pen positions, thus avoiding
+ * smoothing coordinates that are not supposed to be smoothed. This
+ * supposes all noise has been filtered by the lower-level filter,
+ * e.g. by the "variance" module.
+ */
+
+/**
+ * This filter works as follows: we keep track of latest N samples,
+ * and average them with certain weights. The oldest samples have the
+ * least weight and the most recent samples have the most weight.
+ * This helps remove the jitter and at the same time doesn't influence
+ * responsivity because for each input sample we generate one output
+ * sample; pen movement becomes just somehow more smooth.
+ */
+
+#define NR_SAMPHISTLEN	4
+
+/* To keep things simple (avoiding division) we ensure that
+ * SUM(weight) = power-of-two. Also we must know how to approximate
+ * measurements when we have less than NR_SAMPHISTLEN samples.
+ */
+struct ts_hist {
+	int x;
+	int y;
+	int p;
+};
+
+struct tslib_dejitter {
+	unsigned int delta;
+	unsigned int x;
+	unsigned int y;
+	unsigned int down;
+	unsigned int nr;
+	unsigned int head;
+	struct ts_hist *hist /* [NR_SAMPHISTLEN] */;
+	int accum_x, accum_y;
+	int avg_x, avg_y;
+};
+
+static int sqr(int x)
+{
+	return x * x;
+}
+
+static void average (struct tslib_dejitter *djt, int v0, int v1,
+		     int *x, int *y)
+{
+	static int cnt = 0;
+		
+	if (cnt < dejitter_history) {
+		djt->accum_x += v0;
+		djt->accum_y += v1;
+		cnt++;
+	}
+	else {
+		djt->avg_x = djt->accum_x/dejitter_history;
+		djt->avg_y = djt->accum_y/dejitter_history;
+		
+		djt->accum_x += (v0 - djt->avg_x);
+		djt->accum_y += (v1 - djt->avg_y);
+
+		v0 = djt->avg_x;
+		v1 = djt->avg_y;
+	}
+
+	*x = v0;
+	*y = v1;
+}
+
+static void dejitter(struct tslib_dejitter *djt, int x, int y,
+		    unsigned int pressure, int *new_x, int *new_y)
+{
+	/* If the pen moves too fast, reset the backlog. */
+	if (djt->nr) {
+		int prev = (djt->head - 1) & (dejitter_history - 1);
+		if (sqr (x - djt->hist [prev].x) +
+		    sqr (y - djt->hist [prev].y) > djt->delta) {
+			dbg("DEJITTER: pen movement exceeds threshold\n");
+			djt->nr = 0;
+		}
+	}
+
+	djt->hist[djt->head].x = x;
+	djt->hist[djt->head].y = y;
+	if (djt->nr < dejitter_history)
+		djt->nr++;
+
+	/* We'll pass through the very first sample since
+	 * we can't average it (no history yet).
+	 */
+	average(djt, x, y, new_x, new_y);
+	djt->head = (djt->head + 1) & (dejitter_history - 1);
+}
+
+
+/*
+ * wm97xx IO access, all IO locking done by AC97 layer
+ */
+int wm97xx_reg_read(struct wm97xx *wm, u16 reg)
+{
+	if (wm->ac97)
+		return wm->ac97->bus->ops->read(wm->ac97, reg);
+	else
+		return -1;
+}
+EXPORT_SYMBOL_GPL(wm97xx_reg_read);
+
+void wm97xx_reg_write(struct wm97xx *wm, u16 reg, u16 val)
+{
+	/* cache digitiser registers */
+	if(reg >= AC97_WM9713_DIG1 && reg <= AC97_WM9713_DIG3)
+		wm->dig[(reg - AC97_WM9713_DIG1) >> 1] = val;
+
+	/* cache gpio regs */
+	if(reg >= AC97_GPIO_CFG && reg <= AC97_MISC_AFE)
+		wm->gpio[(reg - AC97_GPIO_CFG) >> 1] = val;
+
+	/* wm9713 irq reg */
+	if(reg == 0x5a)
+		wm->misc = val;
+
+	if (wm->ac97)
+		wm->ac97->bus->ops->write(wm->ac97, reg, val);
+}
+EXPORT_SYMBOL_GPL(wm97xx_reg_write);
+
+/**
+ *	wm97xx_read_aux_adc - Read the aux adc.
+ *	@wm: wm97xx device.
+ *  @adcsel: codec ADC to be read
+ *
+ *	Reads the selected AUX ADC.
+ */
+
+int wm97xx_read_aux_adc(struct wm97xx *wm, u16 adcsel)
+{
+	int power_adc = 0, auxval;
+	u16 power = 0;
+
+	/* get codec */
+	mutex_lock(&wm->codec_mutex);
+
+	/* When the touchscreen is not in use, we may have to power up the AUX ADC
+	 * before we can use sample the AUX inputs->
+	 */
+	if (wm->id == WM9713_ID2 &&
+	    (power = wm97xx_reg_read(wm, AC97_EXTENDED_MID)) & 0x8000) {
+		power_adc = 1;
+		wm97xx_reg_write(wm, AC97_EXTENDED_MID, power & 0x7fff);
+	}
+
+	/* Prepare the codec for AUX reading */
+	wm->codec->digitiser_ioctl(wm, WM97XX_AUX_PREPARE);
+
+	/* Turn polling mode on to read AUX ADC */
+	wm->pen_probably_down = 1;
+	wm->codec->poll_sample(wm, adcsel, &auxval);
+
+	if (power_adc)
+		wm97xx_reg_write(wm, AC97_EXTENDED_MID, power | 0x8000);
+
+	wm->codec->digitiser_ioctl(wm, WM97XX_DIG_RESTORE);
+
+	wm->pen_probably_down = 0;
+
+	mutex_unlock(&wm->codec_mutex);
+	return auxval & 0xfff;
+}
+EXPORT_SYMBOL_GPL(wm97xx_read_aux_adc);
+
+/**
+ *	wm97xx_get_gpio - Get the status of a codec GPIO.
+ *	@wm: wm97xx device.
+ *  @gpio: gpio
+ *
+ *	Get the status of a codec GPIO pin
+ */
+
+wm97xx_gpio_status_t wm97xx_get_gpio(struct wm97xx *wm, u32 gpio)
+{
+	u16 status;
+	wm97xx_gpio_status_t ret;
+
+	mutex_lock(&wm->codec_mutex);
+	status = wm97xx_reg_read(wm, AC97_GPIO_STATUS);
+
+	if (status & gpio)
+		ret = WM97XX_GPIO_HIGH;
+	else
+		ret = WM97XX_GPIO_LOW;
+
+	mutex_unlock(&wm->codec_mutex);
+	return ret;
+}
+EXPORT_SYMBOL_GPL(wm97xx_get_gpio);
+
+/**
+ *	wm97xx_set_gpio - Set the status of a codec GPIO.
+ *	@wm: wm97xx device.
+ *  @gpio: gpio
+ *
+ *
+ *	Set the status of a codec GPIO pin
+ */
+
+void wm97xx_set_gpio(struct wm97xx *wm, u32 gpio,
+		     wm97xx_gpio_status_t status)
+{
+	u16 reg;
+
+	mutex_lock(&wm->codec_mutex);
+	reg = wm97xx_reg_read(wm, AC97_GPIO_STATUS);
+
+	if (status & WM97XX_GPIO_HIGH)
+		reg |= gpio;
+	else
+		reg &= ~gpio;
+
+	if (wm->id == WM9712_ID2)
+		wm97xx_reg_write(wm, AC97_GPIO_STATUS, reg << 1);
+	else
+		wm97xx_reg_write(wm, AC97_GPIO_STATUS, reg);
+	mutex_unlock(&wm->codec_mutex);
+}
+EXPORT_SYMBOL_GPL(wm97xx_set_gpio);
+
+/*
+ * Codec GPIO pin configuration, this set's pin direction, polarity,
+ * stickyness and wake up.
+ */
+void wm97xx_config_gpio(struct wm97xx *wm, u32 gpio, wm97xx_gpio_dir_t dir,
+			wm97xx_gpio_pol_t pol, wm97xx_gpio_sticky_t sticky,
+			wm97xx_gpio_wake_t wake)
+{
+	u16 reg;
+
+	mutex_lock(&wm->codec_mutex);
+	reg = wm97xx_reg_read(wm, AC97_GPIO_POLARITY);
+
+	if (pol == WM97XX_GPIO_POL_HIGH)
+		reg |= gpio;
+	else
+		reg &= ~gpio;
+
+	wm97xx_reg_write(wm, AC97_GPIO_POLARITY, reg);
+	reg = wm97xx_reg_read(wm, AC97_GPIO_STICKY);
+
+	if (sticky == WM97XX_GPIO_STICKY)
+		reg |= gpio;
+	else
+		reg &= ~gpio;
+
+	wm97xx_reg_write(wm, AC97_GPIO_STICKY, reg);
+	reg = wm97xx_reg_read(wm, AC97_GPIO_WAKEUP);
+
+	if (wake == WM97XX_GPIO_WAKE)
+		reg |= gpio;
+	else
+		reg &= ~gpio;
+
+	wm97xx_reg_write(wm, AC97_GPIO_WAKEUP, reg);
+	reg = wm97xx_reg_read(wm, AC97_GPIO_CFG);
+
+	if (dir == WM97XX_GPIO_IN)
+		reg |= gpio;
+	else
+		reg &= ~gpio;
+
+	wm97xx_reg_write(wm, AC97_GPIO_CFG, reg);
+	mutex_unlock(&wm->codec_mutex);
+}
+EXPORT_SYMBOL_GPL(wm97xx_config_gpio);
+
+/*
+ * Handle a pen down interrupt.
+ */
+/* static void wm97xx_pen_irq_worker(void *ptr) */
+static void wm97xx_pen_irq_worker(struct work_struct *w)
+{
+/* 	struct wm97xx *wm = (struct wm97xx *) ptr; */
+	struct wm97xx *wm = container_of(w, struct wm97xx, pen_event_work);
+
+	/* do we need to enable the touch panel reader */
+	if (wm->id == WM9705_ID2) {
+		if (wm97xx_reg_read(wm, AC97_WM97XX_DIGITISER_RD) & WM97XX_PEN_DOWN)
+			wm->pen_is_down = 1;
+		else
+			wm->pen_is_down = 0;
+		wake_up_interruptible(&wm->pen_irq_wait);
+	} else {
+		u16 status, pol;
+		mutex_lock(&wm->codec_mutex);
+		status = wm97xx_reg_read(wm, AC97_GPIO_STATUS);
+		pol = wm97xx_reg_read(wm, AC97_GPIO_POLARITY);
+
+		if (WM97XX_GPIO_13 & pol & status) {
+			wm->pen_is_down = 1;
+			wm97xx_reg_write(wm, AC97_GPIO_POLARITY, pol & ~WM97XX_GPIO_13);
+		} else {
+			wm->pen_is_down = 0;
+			wm97xx_reg_write(wm, AC97_GPIO_POLARITY, pol | WM97XX_GPIO_13);
+		}
+
+		if (wm->id == WM9712_ID2)
+			wm97xx_reg_write(wm, AC97_GPIO_STATUS, (status & ~WM97XX_GPIO_13) << 1);
+		else
+			wm97xx_reg_write(wm, AC97_GPIO_STATUS, status & ~WM97XX_GPIO_13);
+		mutex_unlock(&wm->codec_mutex);
+		wake_up_interruptible(&wm->pen_irq_wait);
+	}
+
+	if (!wm->pen_is_down && wm->mach_ops && wm->mach_ops->acc_enabled)
+		wm->mach_ops->acc_pen_up(wm);
+	enable_irq(wm->pen_irq);
+}
+
+/*
+ * Codec PENDOWN irq handler
+ *
+ * We have to disable the codec interrupt in the handler because it can
+ * take upto 1ms to clear the interrupt source. The interrupt is then enabled
+ * again in the slow handler when the source has been cleared.
+ */
+static irqreturn_t wm97xx_pen_interrupt(int irq, void *dev_id)
+{
+	struct wm97xx *wm = (struct wm97xx *) dev_id;
+	disable_irq(wm->pen_irq);
+	queue_work(wm->pen_irq_workq, &wm->pen_event_work);
+	return IRQ_HANDLED;
+}
+
+/*
+ * initialise pen IRQ handler and workqueue
+ */
+static int wm97xx_init_pen_irq(struct wm97xx *wm)
+{
+	u16 reg;
+
+	INIT_WORK(&wm->pen_event_work, wm97xx_pen_irq_worker/* , wm */);
+	if ((wm->pen_irq_workq =
+	     create_singlethread_workqueue("kwm97pen")) == NULL) {
+		err("could not create pen irq work queue");
+		wm->pen_irq = 0;
+		return -EINVAL;
+	}
+
+	if (request_irq (wm->pen_irq, wm97xx_pen_interrupt, SA_SHIRQ, "wm97xx-pen", wm)) {
+		err("could not register codec pen down interrupt, will poll for pen down");
+		destroy_workqueue(wm->pen_irq_workq);
+		wm->pen_irq = 0;
+		return -EINVAL;
+	}
+
+	/* enable PEN down on wm9712/13 */
+	if (wm->id != WM9705_ID2) {
+		reg = wm97xx_reg_read(wm, AC97_MISC_AFE);
+		wm97xx_reg_write(wm, AC97_MISC_AFE, reg & 0xfffb);
+		reg = wm97xx_reg_read(wm, 0x5a);
+		wm97xx_reg_write(wm, 0x5a, reg & ~0x0001);
+	}
+
+	return 0;
+}
+
+/* Private struct for communication between struct wm97xx_tshread
+ * and wm97xx_read_samples */
+struct ts_state {
+		int sleep_time;
+		int min_sleep_time;
+};
+
+static int wm97xx_read_samples(struct wm97xx *wm, struct ts_state *state)
+{
+	struct wm97xx_data data;
+	int rc;
+
+	mutex_lock(&wm->codec_mutex);
+
+/* 	dbg("wm97xx_read_samples"); */
+
+	if (wm->mach_ops && wm->mach_ops->acc_enabled)
+		rc = wm->mach_ops->acc_pen_down(wm);
+	else
+		rc = wm->codec->poll_touch(wm, &data);
+
+	if (rc & RC_PENUP) {
+		if (wm->pen_is_down) {
+			wm->pen_is_down = 0;
+			dbg("pen up");
+			
+			wm->dejitter->nr = 0;
+
+			input_report_abs(wm->input_dev, ABS_PRESSURE, 0);
+			if (enable_btn) {
+				input_report_key(wm->input_dev, BTN_TOUCH, 0);
+			}
+			input_sync(wm->input_dev);
+		} else if (!(rc & RC_AGAIN)) {
+			/* We need high frequency updates only while pen is down,
+			 * the user never will be able to touch screen faster than
+			 * a few times per second... On the other hand, when the
+			 * user is actively working with the touchscreen we don't
+			 * want to lose the quick response. So we will slowly
+			 * increase sleep time after the pen is up and quicky
+			 * restore it to ~one task switch when pen is down again.
+			 */
+			if (state->sleep_time < HZ / 10)
+				state->sleep_time++;
+		}
+
+	} else if (rc & RC_VALID) {
+		dbg("pen down: x=%x:%d, y=%x:%d, pressure=%x:%d\n",
+		    data.x >> 12, data.x & 0xfff, data.y >> 12,
+		    data.y & 0xfff, data.p >> 12, data.p & 0xfff);
+		
+		dejitter(wm->dejitter, data.x & 0xfff, data.y & 0xfff,
+			 data.p & 0xfff, &data.x, &data.y);
+
+		input_report_abs(wm->input_dev, ABS_X, data.x & 0xfff);
+		input_report_abs(wm->input_dev, ABS_Y, data.y & 0xfff);
+		input_report_abs(wm->input_dev, ABS_PRESSURE, data.p & 0xfff);
+		
+		if (!wm->pen_is_down && enable_btn) {
+			input_report_key(wm->input_dev, BTN_TOUCH, 1);
+		}
+		input_sync(wm->input_dev);
+
+		wm->pen_is_down = 1;
+		state->sleep_time = state->min_sleep_time;
+	} else if (rc & RC_PENDOWN) {
+		dbg("pen down");
+		wm->pen_is_down = 1;
+		state->sleep_time = state->min_sleep_time;
+	}
+
+	mutex_unlock(&wm->codec_mutex);
+	return rc;
+}
+
+/*
+ * The touchscreen sample reader thread.
+ */
+static int wm97xx_ts_read(void *data)
+{
+	int rc;
+	struct ts_state state;
+	struct wm97xx *wm = (struct wm97xx *) data;
+
+	/* set up thread context */
+	wm->ts_task = current;
+	daemonize("kwm97xxts");
+
+	if (wm->codec == NULL) {
+		wm->ts_task = NULL;
+		printk(KERN_ERR "codec is NULL, bailing\n");
+	}
+
+	complete(&wm->ts_init);
+	wm->pen_is_down = 0;
+	state.min_sleep_time = HZ >= 100 ? HZ / 100 : 1;
+	if (state.min_sleep_time < 1)
+		state.min_sleep_time = 1;
+	state.sleep_time = state.min_sleep_time;
+
+	/* touch reader loop */
+	while (wm->ts_task) {
+		do {
+			try_to_freeze();
+			rc = wm97xx_read_samples(wm, &state);
+		} while (rc & RC_AGAIN);
+		if (!wm->pen_is_down && wm->pen_irq) {
+			/* Nice, we don't have to poll for pen down event */
+			wait_event_interruptible(wm->pen_irq_wait, wm->pen_is_down);
+		} else {
+			set_task_state(current, TASK_INTERRUPTIBLE);
+			schedule_timeout(state.sleep_time);
+		}
+	}
+	complete_and_exit(&wm->ts_exit, 0);
+}
+
+/**
+ *	wm97xx_ts_input_open - Open the touch screen input device.
+ *	@idev:	Input device to be opened.
+ *
+ *	Called by the input sub system to open a wm97xx touchscreen device.
+ *  Starts the touchscreen thread and touch digitiser.
+ */
+static int wm97xx_ts_input_open(struct input_dev *idev)
+{
+	int ret = 0;
+	struct wm97xx *wm = (struct wm97xx *) idev->private;
+
+	mutex_lock(&wm->codec_mutex);
+	/* first time opened ? */
+	if (wm->ts_use_count++ == 0) {
+		/* start touchscreen thread */
+		init_completion(&wm->ts_init);
+		init_completion(&wm->ts_exit);
+		ret = kernel_thread(wm97xx_ts_read, wm, CLONE_KERNEL);
+
+		if (ret >= 0) {
+			wait_for_completion(&wm->ts_init);
+			if (wm->ts_task == NULL)
+				ret = -EINVAL;
+		} else {
+			mutex_unlock(&wm->codec_mutex);
+			return ret;
+		}
+
+		/* start digitiser */
+		if (wm->mach_ops && wm->mach_ops->acc_enabled)
+			wm->codec->acc_enable(wm, 1);
+		wm->codec->digitiser_ioctl(wm, WM97XX_DIG_START);
+
+		/* init pen down/up irq handling */
+		if (wm->pen_irq) {
+			wm97xx_init_pen_irq(wm);
+
+			if (wm->pen_irq == 0) {
+				/* we failed to get an irq for pen down events,
+				 * so we resort to polling. kickstart the reader */
+				wm->pen_is_down = 1;
+				wake_up_interruptible(&wm->pen_irq_wait);
+			}
+		}
+	}
+
+	mutex_unlock(&wm->codec_mutex);
+	return 0;
+}
+
+/**
+ *	wm97xx_ts_input_close - Close the touch screen input device.
+ *	@idev:	Input device to be closed.
+ *
+ *	Called by the input sub system to close a wm97xx touchscreen device.
+ *  Kills the touchscreen thread and stops the touch digitiser.
+ */
+
+static void wm97xx_ts_input_close(struct input_dev *idev)
+{
+	struct wm97xx *wm = (struct wm97xx *) idev->private;
+
+	mutex_lock(&wm->codec_mutex);
+	if (--wm->ts_use_count == 0) {
+		/* destroy workqueues and free irqs */
+		if (wm->pen_irq) {
+			free_irq(wm->pen_irq, wm);
+			destroy_workqueue(wm->pen_irq_workq);
+		}
+
+		/* kill thread */
+		if (wm->ts_task) {
+			wm->ts_task = NULL;
+			wm->pen_is_down = 1;
+			mutex_unlock(&wm->codec_mutex);
+			wake_up_interruptible(&wm->pen_irq_wait);
+			wait_for_completion(&wm->ts_exit);
+			wm->pen_is_down = 0;
+			mutex_lock(&wm->codec_mutex);
+		}
+
+		/* stop digitiser */
+		wm->codec->digitiser_ioctl(wm, WM97XX_DIG_STOP);
+		if (wm->mach_ops && wm->mach_ops->acc_enabled)
+			wm->codec->acc_enable(wm, 0);
+	}
+	mutex_unlock(&wm->codec_mutex);
+}
+
+/*
+ * Bus interface to allow for client drivers codec access
+ * e.g. battery monitor
+ */
+static int wm97xx_bus_match(struct device *dev, struct device_driver *drv)
+{
+	return !(strcmp(dev->bus_id,drv->name));
+}
+
+/*
+ * The AC97 audio driver will do all the Codec suspend and resume
+ * tasks. This is just for anything machine specific or extra.
+ */
+static int wm97xx_bus_suspend(struct device *dev, pm_message_t state)
+{
+	int ret = 0;
+
+	if (dev->driver && dev->driver->suspend)
+		ret = dev->driver->suspend(dev, state);
+
+	return ret;
+}
+
+static int wm97xx_bus_resume(struct device *dev)
+{
+	int ret = 0;
+
+	if (dev->driver && dev->driver->resume)
+		ret = dev->driver->resume(dev);
+
+	return ret;
+}
+
+struct bus_type wm97xx_bus_type = {
+	.name       = "wm97xx",
+	.match      = wm97xx_bus_match,
+	.suspend    = wm97xx_bus_suspend,
+	.resume     = wm97xx_bus_resume,
+};
+EXPORT_SYMBOL_GPL(wm97xx_bus_type);
+
+static void  wm97xx_release(struct device *dev)
+{
+	kfree(dev);
+}
+
+static int wm97xx_probe(struct device *dev)
+{
+	struct wm97xx* wm;
+	int ret = 0, id = 0;
+
+	if (!(wm = kzalloc(sizeof(struct wm97xx), GFP_KERNEL)))
+		return -ENOMEM;
+
+	if (!(wm->dejitter = kzalloc(sizeof(struct wm97xx), GFP_KERNEL))) {
+		kfree(wm);
+		return -ENOMEM;
+	}
+
+	if (!(wm->dejitter->hist =
+	      kzalloc(sizeof(struct ts_hist)*dejitter_history, GFP_KERNEL))) {
+		kfree(wm->dejitter);
+		kfree(wm);
+		return -ENOMEM;
+	}
+
+	wm->dejitter->delta = sqr(dejitter_delta);
+	wm->dejitter->head = 0;
+
+	mutex_init(&wm->codec_mutex);
+
+	init_waitqueue_head(&wm->pen_irq_wait);
+	wm->dev = dev;
+	dev->driver_data = wm;
+	wm->ac97 = to_ac97_t(dev);
+
+	/* check that we have a supported codec */
+	if ((id = wm97xx_reg_read(wm, AC97_VENDOR_ID1)) != WM97XX_ID1) {
+		err("could not find a wm97xx, found a %x instead\n", id);
+		kfree(wm->dejitter->hist);
+		kfree(wm->dejitter);
+		kfree(wm);
+		return -ENODEV;
+	}
+
+	wm->id = wm97xx_reg_read(wm, AC97_VENDOR_ID2);
+	if(wm->id != wm97xx_codec.id) {
+		err("could not find a the selected codec, please build for wm97%2x", wm->id & 0xff);
+		kfree(wm->dejitter->hist);
+		kfree(wm->dejitter);
+		kfree(wm);
+		return -ENODEV;
+	}
+
+	if((wm->input_dev = input_allocate_device()) == NULL) {
+		kfree(wm->dejitter->hist);
+		kfree(wm->dejitter);
+		kfree(wm);
+		return -ENOMEM;
+	}
+
+	/* set up touch configuration */
+	info("detected a wm97%2x codec", wm->id & 0xff);
+	wm->input_dev->name = "wm97xx touchscreen";
+	wm->input_dev->open = wm97xx_ts_input_open;
+	wm->input_dev->close = wm97xx_ts_input_close;
+	set_bit(EV_ABS, wm->input_dev->evbit);
+	set_bit(ABS_X, wm->input_dev->absbit);
+	set_bit(ABS_Y, wm->input_dev->absbit);
+	set_bit(ABS_PRESSURE, wm->input_dev->absbit);
+	wm->input_dev->absmax[ABS_X] = abs_x[1];
+	wm->input_dev->absmax[ABS_Y] = abs_y[1];
+	wm->input_dev->absmax[ABS_PRESSURE] = abs_p[1];
+	wm->input_dev->absmin[ABS_X] = abs_x[0];
+	wm->input_dev->absmin[ABS_Y] = abs_y[0];
+	wm->input_dev->absmin[ABS_PRESSURE] = abs_p[0];
+	wm->input_dev->absfuzz[ABS_X] = abs_x[2];
+	wm->input_dev->absfuzz[ABS_Y] = abs_y[2];
+	wm->input_dev->absfuzz[ABS_PRESSURE] = abs_p[2];
+
+	set_bit(EV_KEY, wm->input_dev->evbit);
+	wm->input_dev->keybit[LONG(BTN_TOUCH)] = BIT(BTN_TOUCH);
+
+	wm->input_dev->private = wm;
+	wm->codec = &wm97xx_codec;
+	if((ret = input_register_device(wm->input_dev)) < 0) {
+		kfree(wm->dejitter->hist);
+		kfree(wm->dejitter);
+		kfree(wm);
+		return -ENOMEM;
+	}
+
+	/* set up physical characteristics */
+	wm->codec->digitiser_ioctl(wm, WM97XX_PHY_INIT);
+
+	/* load gpio cache */
+	wm->gpio[0] = wm97xx_reg_read(wm, AC97_GPIO_CFG);
+	wm->gpio[1] = wm97xx_reg_read(wm, AC97_GPIO_POLARITY);
+	wm->gpio[2] = wm97xx_reg_read(wm, AC97_GPIO_STICKY);
+	wm->gpio[3] = wm97xx_reg_read(wm, AC97_GPIO_WAKEUP);
+	wm->gpio[4] = wm97xx_reg_read(wm, AC97_GPIO_STATUS);
+	wm->gpio[5] = wm97xx_reg_read(wm, AC97_MISC_AFE);
+
+	/* register our battery device */
+	if (!(wm->battery_dev = kzalloc(sizeof(struct device), GFP_KERNEL))) {
+		ret = -ENOMEM;
+		goto batt_err;
+	}
+	wm->battery_dev->bus = &wm97xx_bus_type;
+	strcpy(wm->battery_dev->bus_id,"wm97xx-battery");
+	wm->battery_dev->driver_data = wm;
+	wm->battery_dev->parent = dev;
+	wm->battery_dev->release = wm97xx_release;
+	if((ret = device_register(wm->battery_dev)) < 0)
+		goto batt_reg_err;
+
+	/* register our extended touch device (for machine specific extensions) */
+	if (!(wm->touch_dev = kzalloc(sizeof(struct device), GFP_KERNEL))) {
+		ret = -ENOMEM;
+		goto touch_err;
+	}
+	wm->touch_dev->bus = &wm97xx_bus_type;
+	strcpy(wm->touch_dev->bus_id,"wm97xx-touchscreen");
+	wm->touch_dev->driver_data = wm;
+	wm->touch_dev->parent = dev;
+	wm->touch_dev->release = wm97xx_release;
+	if((ret = device_register(wm->touch_dev)) < 0)
+		goto touch_reg_err;
+
+	return ret;
+
+  touch_reg_err:
+	kfree(wm->touch_dev);
+  touch_err:
+	device_unregister(wm->battery_dev);
+  batt_reg_err:
+	kfree(wm->battery_dev);
+  batt_err:
+	input_unregister_device(wm->input_dev);
+	kfree(wm->dejitter->hist);
+	kfree(wm->dejitter);
+	kfree(wm);
+	return ret;
+}
+
+static int wm97xx_remove(struct device *dev)
+{
+	struct wm97xx *wm = dev_get_drvdata(dev);
+
+	/* Stop touch reader thread */
+	if (wm->ts_task) {
+		wm->ts_task = NULL;
+		wm->pen_is_down = 1;
+		wake_up_interruptible(&wm->pen_irq_wait);
+		wait_for_completion(&wm->ts_exit);
+	}
+	device_unregister(wm->battery_dev);
+	device_unregister(wm->touch_dev);
+	input_unregister_device(wm->input_dev);
+
+	kfree(wm->dejitter->hist);
+	kfree(wm->dejitter);
+	kfree(wm);
+	return 0;
+}
+
+#ifdef CONFIG_PM
+int wm97xx_resume(struct device* dev)
+{
+	struct wm97xx *wm = dev_get_drvdata(dev);
+
+	/* restore digitiser and gpio's */
+	if(wm->id == WM9713_ID2) {
+		wm97xx_reg_write(wm, AC97_WM9713_DIG1, wm->dig[0]);
+		wm97xx_reg_write(wm, 0x5a, wm->misc);
+		if(wm->ts_use_count) {
+			u16 reg = wm97xx_reg_read(wm, AC97_EXTENDED_MID) & 0x7fff;
+			wm97xx_reg_write(wm, AC97_EXTENDED_MID, reg);
+		}
+	}
+
+	wm97xx_reg_write(wm, AC97_WM9713_DIG2, wm->dig[1]);
+	wm97xx_reg_write(wm, AC97_WM9713_DIG3, wm->dig[2]);
+
+	wm97xx_reg_write(wm, AC97_GPIO_CFG, wm->gpio[0]);
+	wm97xx_reg_write(wm, AC97_GPIO_POLARITY, wm->gpio[1]);
+	wm97xx_reg_write(wm, AC97_GPIO_STICKY, wm->gpio[2]);
+	wm97xx_reg_write(wm, AC97_GPIO_WAKEUP, wm->gpio[3]);
+	wm97xx_reg_write(wm, AC97_GPIO_STATUS, wm->gpio[4]);
+	wm97xx_reg_write(wm, AC97_MISC_AFE, wm->gpio[5]);
+
+	return 0;
+}
+
+#else
+#define wm97xx_resume		NULL
+#endif
+
+/*
+ * Machine specific operations
+ */
+int wm97xx_register_mach_ops(struct wm97xx *wm, struct wm97xx_mach_ops *mach_ops)
+{
+	mutex_lock(&wm->codec_mutex);
+	if(wm->mach_ops) {
+		mutex_unlock(&wm->codec_mutex);
+		return -EINVAL;
+	}
+	wm->mach_ops = mach_ops;
+	mutex_unlock(&wm->codec_mutex);
+	return 0;
+}
+EXPORT_SYMBOL_GPL(wm97xx_register_mach_ops);
+
+void wm97xx_unregister_mach_ops(struct wm97xx *wm)
+{
+	mutex_lock(&wm->codec_mutex);
+	wm->mach_ops = NULL;
+	mutex_unlock(&wm->codec_mutex);
+}
+EXPORT_SYMBOL_GPL(wm97xx_unregister_mach_ops);
+
+static struct device_driver wm97xx_driver = {
+	.name = 	"ac97",
+	.bus = 		&ac97_bus_type,
+	.owner = 	THIS_MODULE,
+	.probe = 	wm97xx_probe,
+	.remove = 	wm97xx_remove,
+	.resume =	wm97xx_resume,
+};
+
+static int __init wm97xx_init(void)
+{
+	int ret;
+
+	info("version %s liam.girdwood@wolfsonmicro.com", WM_CORE_VERSION);
+	if((ret = bus_register(&wm97xx_bus_type)) < 0)
+		return ret;
+	return driver_register(&wm97xx_driver);
+}
+
+static void __exit wm97xx_exit(void)
+{
+	driver_unregister(&wm97xx_driver);
+	bus_unregister(&wm97xx_bus_type);
+}
+
+module_init(wm97xx_init);
+module_exit(wm97xx_exit);
+
+/* Module information */
+MODULE_AUTHOR("Liam Girdwood, liam.girdwood@wolfsonmicro.com, www.wolfsonmicro.com");
+MODULE_DESCRIPTION("WM97xx Core - Touch Screen / AUX ADC / GPIO Driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/video/geode/Kconfig b/drivers/video/geode/Kconfig
index a814b6c..f076498 100644
--- a/drivers/video/geode/Kconfig
+++ b/drivers/video/geode/Kconfig
@@ -8,6 +8,30 @@ config FB_GEODE
 	  Say 'Y' here to allow you to select framebuffer drivers for
 	  the AMD Geode family of processors.
 
+config FB_GEODE_LX
+	bool "AMD Geode LX framebuffer"
+	depends on FB_GEODE && MGEODE_LX
+	select CIMARRON
+	help
+	  This is the framebuffer device driver for the AMD Geode LX processor.
+	  Select this option to enable accelerated console support.  To compile
+	  this driver as a module, chose 'M' here; the module will be called
+	  geodefb
+
+config FB_GEODE_ACCEL
+	bool "AMD Geode LX console acceleration"
+	depends on FB_GEODE_LX
+	help
+	  Say y here to enable accelerated drawing for the Geode framebuffer
+
+config FB_GEODE_PANEL
+	bool "AMD Geode Framebuffer panel support"
+	depends on FB_GEODE_LX
+	help
+	  Say y here to enable flatpanel support in the Geode framebuffer
+	  driver
+
+
 config FB_GEODE_GX
 	tristate "AMD Geode GX framebuffer support (EXPERIMENTAL)"
 	depends on FB && FB_GEODE && EXPERIMENTAL
diff --git a/drivers/video/geode/Makefile b/drivers/video/geode/Makefile
index f896565..958e518 100644
--- a/drivers/video/geode/Makefile
+++ b/drivers/video/geode/Makefile
@@ -1,5 +1,12 @@
 # Makefile for the Geode family framebuffer drivers
 
+EXTRA_CFLAGS += -Ilib/cimarron/ -DREAL_SILICON 
+
+my-obj-$(CONFIG_FB_GEODE_LX) += geodefb_lx.o 
+my-obj-$(CONFIG_FB_GEODE_ACCEL) += geodefb_lx_accel.o
+
+obj-$(CONFIG_FB_GEODE) += geodefb.o geodefb_modes.o geodefb_hw.o $(my-obj-y)
+
 obj-$(CONFIG_FB_GEODE_GX1) += gx1fb.o
 obj-$(CONFIG_FB_GEODE_GX)  += gxfb.o
 
diff --git a/drivers/video/geode/build_num.h b/drivers/video/geode/build_num.h
new file mode 100644
index 0000000..72a07e8
--- /dev/null
+++ b/drivers/video/geode/build_num.h
@@ -0,0 +1,36 @@
+#ifndef BUILD_NUM_H
+#define BUILD_NUM_H
+
+#ifdef AMD_BUILDNUM_DEFINED
+#error "Caution:  You have muliple version files in your path.  Please correct this."
+#endif
+
+#define AMD_BUILDNUM_DEFINED
+
+/* Define the following for your driver */
+
+#define _NAME "AMD Geode LX Accelerated Framebuffer driver"
+#define _MAJOR 01
+#define _MINOR 03
+
+/* This defines the current buildlevel and revision of the code */
+#define _BL        01
+#define _BLREV     00
+
+#ifdef _BLREV
+#define _BUILDLEVEL _x(_BL)_x(_BLREV)
+#else
+#define _BUILDLEVEL _x(_BL)
+#endif
+
+/* Use this macro to get the version string */
+
+#define _VERSION_NUMBER _x(_MAJOR) "." _x(_MINOR) "." _BUILDLEVEL
+#define AMD_VERSION _NAME " " _VERSION_NUMBER
+
+/* Syntatic sugar for use above - you probably don't have to touch this */
+
+#define _x(s) _s(s)
+#define _s(s) #s
+
+#endif
diff --git a/drivers/video/geode/geodefb.c b/drivers/video/geode/geodefb.c
new file mode 100644
index 0000000..1b9ba88
--- /dev/null
+++ b/drivers/video/geode/geodefb.c
@@ -0,0 +1,284 @@
+/* <LIC_AMD_STD>
+ * Copyright (c) 2004-2005 Advanced Micro Devices, Inc.
+ * 
+ * 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
+ * 
+ * The full GNU General Public License is included in this distribution in the
+ * file called COPYING
+ * </LIC_AMD_STD>  */
+/* <CTL_AMD_STD>
+ * </CTL_AMD_STD>  */
+/* <DOC_AMD_STD>
+ * Geode framebuffer driver
+ * </DOC_AMD_STD>  */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/string.h>
+#include <linux/fb.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+
+#include <asm/errno.h>
+
+#include <cim/cim_parm.h>
+#include <cim/cim_rtns.h>
+
+/* module and KFB options */
+
+char vmode[15] = {0};
+int compression = 0;   /* Compression support default off */
+int vfreq = 60;        /* vertical refresh default 60 */
+int maxmem = (720 * 2 * 8192) / 1024;  /* 12288K */
+int accel = 1;
+
+#ifdef CONFIG_FB_GEODE_PANEL
+int flatpanel = 1;  /* Flatpanel support default off when FP is enabled */
+int fphwscale = 1;  /* HW scaling default on when FP is enabled*/
+#endif
+
+#ifdef MODULE
+
+MODULE_AUTHOR("Advanced Micro Devices, Inc.");
+MODULE_DESCRIPTION("Accelerated Framebuffer driver for AMD Geode devices");
+MODULE_LICENSE("GPL");
+
+MODULE_PARM(vfreq, "i");
+MODULE_PARM_DESC(vfreq, "Set default video refresh rate");
+
+MODULE_PARM(vmode, "s");
+MODULE_PARM_DESC(vmode, "Set inital mode to <xres>x<vres>@refresh-bpp");
+
+MODULE_PARM(compression, "i");
+MODULE_PARM_DESC(compression, "Compression support (0=disabled or 1=enabled)");
+
+MODULE_PARM(maxmem, "i");
+MODULE_PARM_DESC(maxmem, "Maximum amount of memory to use for the FB (in K)");
+
+MODULE_PARM(accel, "i");
+MODULE_PARM_DESC(accel, "HW accleration support (0=disabled or 1=enabled)");
+
+#ifdef CONFIG_FB_GEODE_PANEL
+MODULE_PARM(flatpanel, "i");
+MODULE_PARM_DESC(flatpanel, "Flatpanel support (0=disabled or 1=enabled)");
+
+MODULE_PARM(fphwscale, "i");
+MODULE_PARM_DESC(fphwscale, "FP Hardware Scaling (0=disabled or 1=enabled)");
+#endif
+
+#endif
+
+#ifdef CONFIG_FB_GEODE_LX
+extern int lxfb_init(struct device *);
+extern void lxfb_cleanup(void);
+extern int lxfb_suspend(struct device *dev, u32 state, u32 level);
+extern int lxfb_resume(struct device *dev, u32 level);
+#endif
+
+struct geodefb_funcs {
+  int cpu;
+  int (*init)(struct device *);
+  void (*cleanup)(void);
+  int (*suspend)(struct device *, u32, u32);
+  int (*resume)(struct device *, u32);
+};
+
+static struct geodefb_funcs geode_cpus[] = {
+#ifdef CONFIG_FB_GEODE_LX
+  { CIM_CPU_GEODELX, 
+	  lxfb_init, 
+	  lxfb_cleanup, 
+	  lxfb_suspend, 
+	  lxfb_resume },
+#endif
+  { 0, NULL, NULL }
+};
+
+static struct geodefb_funcs *geodefb_cpu = 0;
+
+/* FIXME: __init? */
+
+static int detect_geode_cpu(void) {
+  unsigned long cpu, companion;
+  int f = 0;
+
+  /* This returns both the CPU and the companion chip */
+  init_detect_cpu(&cpu, &companion);
+  
+  while(geode_cpus[f].cpu) {
+    if (geode_cpus[f].cpu == (cpu & 0xFF)) {
+      geodefb_cpu = &geode_cpus[f];
+      break;
+    }
+    f++;
+  }
+
+  if (!geodefb_cpu) {
+    printk(KERN_ERR "GEODEFB:  Unknown CPU detected (%lx)n", cpu);
+    return -ENODEV;
+  }
+      
+  return 0;
+}
+
+/* FIXME:  Don't build if we aren't a module? */
+
+#define TYPE_INT    0x1
+#define TYPE_STRING 0x2
+#define TYPE_FLAG   0x3
+
+struct geodefb_opts_t {
+  char *option;
+  int type;
+  void *ptr;
+  int size;
+};
+
+static struct geodefb_opts_t geodefb_options[] __initdata = {
+  { "vfreq", TYPE_INT, &vfreq, sizeof(vfreq) },
+  { "vmode", TYPE_STRING, vmode, sizeof(vmode) },
+  { "compression", TYPE_FLAG, &compression, 0 },
+  { "maxmem", TYPE_INT, &maxmem, sizeof(maxmem) },
+  { "accel", TYPE_FLAG, &accel, 0 },
+#ifdef CONFIG_FB_GEODE_PANEL
+  { "flatpanel", TYPE_FLAG, &flatpanel, 0 },
+  { "fphwscale", TYPE_FLAG, &fphwscale, 0 },
+#endif
+  { "", 0, 0 }
+};
+
+int __init
+geodefb_setup(char *options) {
+
+  char *opt;
+  int o;
+
+  if (!options || !*options)
+    return 0;
+
+  while((opt = strsep(&options, ","))) {
+    if (!*opt) continue;
+    
+    for(o = 0; geodefb_options[o].type; o++) {
+      struct geodefb_opts_t *p = &geodefb_options[o];
+
+      if (p->type == TYPE_FLAG) {
+	int flag = 1;
+	char *ptr = opt;
+
+	/* Allow them to say "no<token> */
+	if (!strncmp(ptr, "no", 2)) {
+	  flag = 0;
+	  ptr += 2;
+	}
+				    
+	if (!strcmp(ptr,p->option)) {
+	  *((int *) p->ptr) = flag;
+	  break;
+	}
+
+      } else {
+	if (strncmp(opt, p->option, strlen(p->option))) 
+	  continue;
+	
+	if (*(opt + strlen(p->option)) != '=')
+	  continue;
+	
+	if (p->type == TYPE_INT) {
+	  *((int *) p->ptr) = 
+	    simple_strtoul(opt + strlen(p->option) + 1, NULL, 0);
+	}
+	else if (p->type == TYPE_STRING) {
+	  strncpy((char *) p->ptr, opt + strlen(p->option) + 1, p->size);
+	}
+	
+	break;
+      }
+    }
+  }
+
+  return 0;
+}
+
+static int geodefb_suspend(struct device *dev, u32 state, u32 level) {
+  if (geodefb_cpu)
+    return geodefb_cpu->suspend(dev, state, level);
+  return 0;
+}
+
+static int geodefb_resume(struct device *dev, u32 level) {
+  if (geodefb_cpu)
+    return geodefb_cpu->resume(dev, level);
+  return 0;
+}
+
+static int __init 
+geodefb_probe(struct device *device) {
+  
+  if (detect_geode_cpu()) return -ENODEV;
+  return geodefb_cpu->init(device);
+}
+
+static struct device_driver geodefb_driver = {
+        .name   = "geodefb",
+        .bus    = &platform_bus_type,
+        .probe  = geodefb_probe,
+	.suspend = geodefb_suspend,
+	.resume = geodefb_resume
+};
+
+static struct platform_device geodefb_device = {
+        .name   = "geodefb",
+};
+
+
+int __init
+geodefb_init(void)
+{
+  char *option = NULL;
+  int ret;
+
+  if (fb_get_options("geodefb", &option))
+    return -ENODEV;
+  
+  geodefb_setup(option);
+  
+  ret = driver_register(&geodefb_driver);
+
+  if (!ret) {    
+    ret = platform_device_register(&geodefb_device);
+
+    if (ret)
+      driver_unregister(&geodefb_driver);
+  }
+
+  return ret;
+}
+
+#ifdef MODULE
+void __exit
+geodefb_exit(void)
+{
+  if (geodefb_cpu)
+    geodefb_cpu->cleanup();
+}
+#endif
+
+module_init(geodefb_init);
+
+#ifdef MODULE
+module_exit(geodefb_exit);
+#endif
diff --git a/drivers/video/geode/geodefb.h b/drivers/video/geode/geodefb.h
index ae04820..06c0b59 100644
--- a/drivers/video/geode/geodefb.h
+++ b/drivers/video/geode/geodefb.h
@@ -12,6 +12,40 @@
 #ifndef __GEODEFB_H__
 #define __GEODEFB_H__
 
+#include <linux/fb.h>
+
+#define GEODEFB_CRT_DEV   0x01
+#define GEODEFB_PANEL_DEV 0x02
+
+struct geodefb_panel_info {
+  int refresh;
+  int xres;
+  int yres;
+};
+
+
+struct geodefb_mode {
+  int xres;
+  int yres;
+  int refresh;
+  int depth;
+};
+
+#define FB_HZ     0
+#define FB_HTOTAL 1
+#define FB_VTOTAL 2
+#define FB_FREQ   3
+
+#define GEODEFB_GET_HZ(var)       geodefb_get_timings(var, 0, FB_HZ)
+#define GEODEFB_GET_HTOTAL(var)   geodefb_get_timings(var, 0, FB_HTOTAL)
+#define GEODEFB_GET_VTOTAL(var)   geodefb_get_timings(var, 0, FB_VTOTAL)
+#define GEODEFB_GET_FREQ(var, hz) geodefb_get_timings(var, hz, FB_FREQ)
+
+unsigned int geodefb_get_devices(void);
+int geodefb_get_panel_info(struct geodefb_panel_info *);
+void geodefb_parse_mode(const char *, struct geodefb_mode *);
+int geodefb_get_timings(struct fb_var_screeninfo *var, int hz, int flag);
+
 struct geodefb_info;
 
 struct geode_dc_ops {
diff --git a/drivers/video/geode/geodefb_hw.c b/drivers/video/geode/geodefb_hw.c
new file mode 100644
index 0000000..f0ecbe9
--- /dev/null
+++ b/drivers/video/geode/geodefb_hw.c
@@ -0,0 +1,105 @@
+/* <LIC_AMD_STD>
+ * Copyright (c) 2004-2005 Advanced Micro Devices, Inc.
+ * 
+ * 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
+ * 
+ * The full GNU General Public License is included in this distribution in the
+ * file called COPYING
+ * </LIC_AMD_STD>  */
+/* <CTL_AMD_STD>
+ * </CTL_AMD_STD>  */
+/* <DOC_AMD_STD>
+ * Geode hardware specific routines
+ * </DOC_AMD_STD>  */
+
+#include "geodefb.h"
+
+/* Device specific stuff */
+/* Each platform should define READ_VG */
+
+#ifdef CONFIG_FB_GEODE_LX
+
+#define READ_VG(reg) lx_read_vg(reg)
+
+extern void cim_outw(unsigned short port, unsigned short data);
+extern unsigned short cim_inw(unsigned short port);
+
+unsigned short lx_read_vg(unsigned char reg) {
+
+  unsigned short out;
+
+  cim_outw(0xAC1C, 0xFC53);
+  cim_outw(0xAC1C, 0x0200 | reg);
+
+  out = cim_inw(0xAC1E);
+  
+  return out;
+}
+
+#endif
+
+#ifndef READ_VG
+#error "geodefb:  No processor was selected - probably due to a corrupted config"
+#endif
+
+/* List of refresh values from the FP config register */
+
+static int geodefb_panel_refresh[7] = 
+  { 60, 70, 72, 75, 85, 90, 100 };
+
+/* List of panel resolutiosn from the FP config register */
+
+static struct {
+  int xres;
+  int yres;
+} geodefb_panel_res[] = {
+  { 320, 240 },
+  { 640, 480 },
+  { 800, 600 },
+  { 1024, 768 },
+  { 1152, 864 },
+  { 1280, 1024 },
+  { 1600, 1200 }
+};
+
+int geodefb_get_panel_info(struct geodefb_panel_info *info) {
+  
+  unsigned short reg = READ_VG(0x02);
+  
+  /* refresh rate */
+  
+  info->refresh = geodefb_panel_refresh[(reg >> 13) & 0x7];
+  info->xres = geodefb_panel_res[(reg >> 3) & 0x07].xres;
+  info->yres = geodefb_panel_res[(reg >> 3) & 0x07].yres;
+
+  return 0;
+}
+
+unsigned int geodefb_get_devices(void) {
+  unsigned short reg = READ_VG(0x0);
+
+  switch((reg >> 8) & 0x7) {
+  case 0:
+    return GEODEFB_CRT_DEV;
+
+  case 1:
+    return GEODEFB_PANEL_DEV;
+    
+  case 5:
+    return GEODEFB_CRT_DEV | GEODEFB_PANEL_DEV;
+  }
+
+  return 0;
+}
diff --git a/drivers/video/geode/geodefb_lx.c b/drivers/video/geode/geodefb_lx.c
new file mode 100644
index 0000000..3ed09ae
--- /dev/null
+++ b/drivers/video/geode/geodefb_lx.c
@@ -0,0 +1,804 @@
+/* <LIC_AMD_STD>
+ * Copyright (c) 2004-2005 Advanced Micro Devices, Inc.
+ * 
+ * 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
+ * 
+ * The full GNU General Public License is included in this distribution in the
+ * file called COPYING
+ * </LIC_AMD_STD>  */
+/* <CTL_AMD_STD>
+ * </CTL_AMD_STD>  */
+/* <DOC_AMD_STD>
+ * Geode LX framebuffer driver
+ * </DOC_AMD_STD>  */
+
+/* #include <linux/config.h> */
+#include <linux/module.h>
+#include <linux/kernel.h>
+
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/tty.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/pm.h>
+#include <linux/platform_device.h>
+
+/* For the console notifier */
+/* #include <linux/vt_kern.h> */
+
+#include <cim_mem.h>
+
+#include <cim/cim_parm.h>
+#include <cim/cim_rtns.h>
+
+#include "geodefb.h"
+#include "geodefb_lx.h"
+
+#include "build_num.h"
+
+extern char vmode[15];
+extern int compression;
+extern int vfreq;
+extern int maxmem;
+extern int accel;
+
+#ifdef CONFIG_FB_GEODE_PANEL
+extern int flatpanel;
+extern int fphwscale;
+static struct geodefb_panel_info panel_info;
+#endif
+
+/* Cimarron */
+
+extern void cim_outb(unsigned short port, unsigned char data);
+extern unsigned char cim_inb(unsigned short port);
+extern void cim_outw(unsigned short port, unsigned short data);
+
+extern struct notifier_block *console_notifier_list;
+
+/* Macros */
+
+#define LXFB_FBINFO_FLAGS (FBINFO_DEFAULT | \
+			   FBINFO_HWACCEL_COPYAREA | \
+			   FBINFO_HWACCEL_FILLRECT | \
+			   FBINFO_HWACCEL_IMAGEBLIT | \
+			   FBINFO_HWACCEL_XPAN | \
+			   FBINFO_HWACCEL_YPAN)
+
+#define GEODEFB_DEFAULT_XRES  640
+#define GEODEFB_DEFAULT_YRES  480
+#define GEODEFB_DEFAULT_DEPTH  16
+
+/* Local variables */
+static struct fb_info *fbinfo;
+static int lxfb_palette[16];
+
+static int  active_devices;
+
+static struct geodefb_mode initial_mode = {
+	xres:  GEODEFB_DEFAULT_XRES,
+	yres:  GEODEFB_DEFAULT_YRES,
+	depth: GEODEFB_DEFAULT_DEPTH
+};
+static struct geodefb_mode initial_mode;
+
+struct fb_fix_screeninfo lxfb_fix = {
+        id:        "AMD LX",
+	type:      FB_TYPE_PACKED_PIXELS,
+	visual:    FB_VISUAL_TRUECOLOR,
+	xpanstep:  8,
+	ywrapstep: 1,
+	ypanstep:  0,
+	accel:     FB_ACCEL_NONE
+};
+
+/* ======= Utility variables ======= */
+
+int
+lxfb_get_pitch(int xres, int bpp)
+{
+	int d = xres * (bpp >> 3);
+   
+	if (d > 4096) return 8192;
+	if (d > 2048) return 4096;
+	if (d > 1024) return 2048;
+
+	return 1024;
+}
+
+static int
+lxfb_get_refresh(VG_DISPLAY_MODE *mode) {
+	switch(mode->internal_flags & VG_SUPPORTFLAG_HZMASK) {
+		case VG_SUPPORTFLAG_56HZ: return 56;
+		case VG_SUPPORTFLAG_60HZ: return 60;
+		case VG_SUPPORTFLAG_70HZ: return 70;
+		case VG_SUPPORTFLAG_72HZ: return 72;
+		case VG_SUPPORTFLAG_75HZ: return 75;
+		case VG_SUPPORTFLAG_85HZ: return 85;
+		case VG_SUPPORTFLAG_90HZ: return 90;
+		case VG_SUPPORTFLAG_100HZ: return 100;
+	}
+	return 60;
+}
+
+void
+lxfb_clear_active(struct lxfb_par *par, int xres, int yres, int bpp) 
+{
+	int pitch = lxfb_get_pitch(xres,bpp);
+
+#ifdef CONFIG_FB_GEODE_ACCEL
+	if (par->accel == ACCEL_ACTIVE) {
+		gp_declare_blt(0);
+		gp_set_raster_operation(0xF0);  
+		gp_set_solid_pattern(0);
+		gp_set_strides(pitch, 0);
+    
+		gp_pattern_fill(0, xres, yres);
+		gp_wait_blt_pending();    
+	} else 
+#endif
+	{
+		memset(par->fbvirt, 0, yres * pitch);
+	}
+}
+
+/* From 2.4 - check to see if the timings have changed */
+/* AUDIT:  Is this still needed?                       */
+
+static int lxfb_timings_changed(struct fb_var_screeninfo *old, 
+				struct fb_var_screeninfo *new) {
+	
+	if (old->pixclock != new->pixclock) return 1;
+	if (old->left_margin != new->left_margin) return 1;
+	if (old->right_margin != new->right_margin) return 1;
+	if (old->upper_margin != new->upper_margin) return 1;
+	if (old->lower_margin != new->lower_margin) return 1;
+	if (old->hsync_len != new->hsync_len) return 1;
+	if (old->vsync_len != new->vsync_len) return 1;
+
+	return 0;
+}
+
+
+/* Not just timings - this should result in a fairly sane var structure */
+
+static void
+lxfb_set_timings(struct fb_var_screeninfo *var, int mnum) {
+
+	VG_DISPLAY_MODE mode;
+	vg_get_display_mode_information(mnum, &mode);
+  
+	var->hsync_len = mode.hsyncend - mode.hsyncstart;
+	var->vsync_len = mode.vsyncend - mode.vsyncstart;
+  
+	var->right_margin = var->left_margin =
+		(mode.htotal - mode.hactive - var->hsync_len) / 2;
+	var->upper_margin = var->lower_margin =
+		(mode.vtotal - mode.vactive - var->vsync_len) / 2;
+
+	var->pixclock = GEODEFB_GET_FREQ(var, lxfb_get_refresh(&mode));
+
+	var->sync = 0;
+  
+	if (!(mode.flags & VG_MODEFLAG_NEG_HSYNC))
+		var->sync |= FB_SYNC_HOR_HIGH_ACT;
+  
+	if (!(mode.flags & VG_MODEFLAG_NEG_VSYNC))
+		var->sync |= FB_SYNC_VERT_HIGH_ACT;
+  
+	if (mode.flags & VG_MODEFLAG_INTERLACED) {
+		var->vmode = FB_VMODE_INTERLACED;
+  
+		if (mode.flags & VG_MODEFLAG_INT_LINEDOUBLE)
+			var->vmode |= FB_VMODE_DOUBLE;
+	}
+	else
+		var->vmode = FB_VMODE_NONINTERLACED;
+
+	var->width = var->height = -1;  
+
+	switch (var->bits_per_pixel) {
+    
+		case 8: 
+			var->red.offset = 0;
+			var->red.length = 6;
+			var->red.msb_right = 0;
+			var->blue = var->green = var->red;   
+			break;
+    
+		case 16: /* 5-6-5 */
+			var->red.offset = 11;
+			var->red.length = 5;
+			var->green.offset = 5;
+			var->green.length = 6;
+			var->blue.offset = 0;
+			var->blue.length = 5;
+			var->transp.offset = 0;
+			var->transp.length = 0;
+			break;
+
+		case 32: /* A-8-8-8 */
+			var->transp.offset = 24;
+			var->transp.length = 8;
+			var->red.offset = 16;
+			var->red.length = 8;
+			var->green.offset = 8;
+			var->green.length = 8;
+			var->blue.offset = 0;
+			var->blue.length = 8;   
+			break;
+	}
+
+	if (var->xres > var->xres_virtual) 
+		var->xres_virtual = var->xres;
+  
+	if (var->yres > var->yres_virtual)
+		var->yres_virtual = var->yres;
+  
+	if (var->xoffset < 0) var->xoffset = 0;
+	if (var->yoffset < 0) var->yoffset = 0;
+
+	if (var->xoffset > var->xres_virtual - var->xres) 
+		var->xoffset = var->xres_virtual - var->xres;
+  
+	if (var->yoffset > var->yres_virtual - var->yres) 
+		var->yoffset = var->yres_virtual - var->yres;
+  
+	var->red.msb_right = 0;
+	var->green.msb_right = 0;
+	var->blue.msb_right = 0;
+	var->transp.msb_right = 0;
+}
+
+static void
+lxfb_set_mode(struct lxfb_par *par, struct fb_var_screeninfo *var) {
+
+	int bpp = var->bits_per_pixel;
+	int hz = GEODEFB_GET_HZ(var);  
+
+	if (compression)
+		vg_set_compression_enable(0);
+  
+#ifdef CONFIG_FB_GEODE_PANEL
+	if (active_devices & GEODEFB_PANEL_DEV) {
+		int axres = var->xres, ayres = var->yres;
+		int flags = (active_devices & GEODEFB_CRT_DEV) ? VG_MODEFLAG_CRT_AND_FP : 0;
+    
+		if (fphwscale && panel_info.xres >= var->xres && var->xres <= 1024) {
+			axres = panel_info.xres;
+			ayres = panel_info.yres;
+		}
+    
+		vg_set_panel_mode(var->xres, var->yres, axres, ayres, 
+				  panel_info.xres, panel_info.yres, bpp, flags);
+    
+		vg_set_border_color(0x0);  /* Make sure the border is clear */
+	}
+	else if (active_devices & GEODEFB_CRT_DEV)
+#endif
+	{
+		vg_set_display_mode(var->xres, var->yres,
+				    var->xres, var->yres, bpp, hz, 0);
+    
+	}
+  
+	if (var->xres_virtual > var->xres) 
+		vg_set_display_pitch(lxfb_get_pitch(var->xres_virtual, bpp));
+
+	df_set_crt_enable(DF_CRT_ENABLE);
+
+#ifdef CONFIG_FB_GEODE_ACCEL
+	gp_set_bpp(bpp);
+#endif
+
+	lxfb_clear_active(par, var->xres_virtual, var->yres_virtual, bpp);  
+
+	/* Try to turn on compression if we can */
+	/* We do not enable compresssion if panning is even possible */
+  
+	if (compression && var->xres_virtual == var->xres &&
+	    var->yres_virtual == var->yres) {
+		VG_COMPRESSION_DATA data;
+    
+		data.pitch = 544;
+		data.size = 544;
+		data.compression_offset = var->yres * lxfb_get_pitch(var->xres, bpp);
+		vg_configure_compression(&data);
+
+		vg_set_compression_enable(1);
+	}
+
+	par->vfreq = hz;
+};
+
+static int
+lxfb_find_mode(struct lxfb_par *par, struct fb_var_screeninfo *var, 
+	       struct geodefb_mode *mode) {
+
+	VG_QUERY_MODE query;
+	int mnum = 0;
+
+	query.query_flags = VG_QUERYFLAG_BPP | VG_QUERYFLAG_REFRESH;
+	query.bpp = mode->depth;
+  
+#ifdef CONFIG_FB_GEODE_PANEL
+	if (active_devices & GEODEFB_PANEL_DEV) {
+		query.query_flags |= VG_QUERYFLAG_PANEL;
+    		query.query_flags  |= VG_QUERYFLAG_PANELWIDTH | VG_QUERYFLAG_PANELHEIGHT;
+		query.panel_width = panel_info.xres;
+		query.panel_height = panel_info.yres;
+		
+		query.hz = panel_info.refresh;
+	} else
+#endif
+	{
+		query.query_flags |= VG_QUERYFLAG_ACTIVEWIDTH | VG_QUERYFLAG_ACTIVEHEIGHT;
+
+		query.active_width = mode->xres;
+		query.active_height = mode->yres;
+		query.hz = mode->refresh;
+	}
+
+	mnum = vg_get_display_mode_index(&query);
+	if (mnum < 0) return -EINVAL;
+  
+	var->xres_virtual = var->xres = mode->xres;
+	var->yres_virtual = var->yres = mode->yres;
+
+	if (mode->depth <= 8) 
+		var->bits_per_pixel = 8;
+	else if (mode->depth <= 16)
+		var->bits_per_pixel = 16;
+	else if (mode->depth <= 32)
+		var->bits_per_pixel = 32;
+  
+	lxfb_set_timings(var, mnum);
+
+	if (par->accel & ACCEL_AVAILABLE_MASK)
+		var->accel_flags = 1;
+
+	return 0;
+}
+
+/* ======= FB Functions ======= */
+
+static int
+lxfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info) {
+
+	struct lxfb_par *par = (struct lxfb_par *) info->par;
+	VG_QUERY_MODE query;
+	int mode;
+	unsigned int mem;
+
+	/* Adjust the bpp if it comes in screwy */
+
+	if (var->bits_per_pixel <= 8)
+		var->bits_per_pixel = 8;
+	else if (var->bits_per_pixel <= 16)
+		var->bits_per_pixel = 16;
+	else if (var->bits_per_pixel <= 32)
+		var->bits_per_pixel = 32;
+
+	/* See if we have enough room for this mode */
+
+	mem = lxfb_get_pitch(var->xres, var->bits_per_pixel) * var->yres;
+  
+	if (mem > par->fbsize) 
+		return -EINVAL;
+
+	query.query_flags = VG_QUERYFLAG_BPP | VG_QUERYFLAG_REFRESH;
+	query.bpp = var->bits_per_pixel;
+		
+#ifdef CONFIG_FB_GEODE_PANEL
+	if (active_devices & GEODEFB_PANEL_DEV) {
+		query.query_flags |= VG_QUERYFLAG_PANEL;
+    		query.query_flags  |= VG_QUERYFLAG_PANELWIDTH | VG_QUERYFLAG_PANELHEIGHT;
+		query.panel_width = panel_info.xres;
+		query.panel_height = panel_info.yres;
+		query.hz = panel_info.refresh;   
+	}
+	else if (active_devices & GEODEFB_CRT_DEV)
+#endif
+	{
+		query.query_flags |= VG_QUERYFLAG_ACTIVEWIDTH | VG_QUERYFLAG_ACTIVEHEIGHT;
+
+		query.active_width = var->xres;
+		query.active_height = var->yres;
+
+		if (lxfb_timings_changed(&info->var, var))
+			query.hz = GEODEFB_GET_HZ(var);
+		else
+			query.hz = par->vfreq;
+	}
+
+	mode = vg_get_display_mode_index(&query);
+
+	if (mode < 0)
+		return -EINVAL;
+
+	/* Set up the timing tables correctly for the given mode */
+	lxfb_set_timings(var, mode);
+
+	/* Don't allow acceleration, even if the user asks for it */
+
+	if (!(par->accel & ACCEL_AVAILABLE_MASK))
+		var->accel_flags = 0;
+		
+	return 0;
+}
+
+static int
+lxfb_set_par(struct fb_info *info) {
+
+	struct lxfb_par *par = (struct lxfb_par *) info->par;
+	
+	if (par->accel & ACCEL_ACTIVE_MASK)
+		par->accel = ACCEL_NOT_READY;
+	
+	/* Set up the pointers before we try to set the mode */
+
+#ifdef CONFIG_FB_GEODE_ACCEL
+	if (info->var.accel_flags && (par->accel & ACCEL_AVAILABLE_MASK)) {
+		gp_set_frame_buffer_base (par->fbphys, par->fbsize);
+		gp_set_command_buffer_base(par->gpphys, 0, par->gpsize);
+	}
+#endif
+
+	lxfb_set_mode(par, &info->var);
+ 		
+	info->fix.line_length = lxfb_get_pitch(info->var.xres_virtual, 
+					       info->var.bits_per_pixel);
+	info->fix.visual = (info->var.bits_per_pixel == 8) 
+		? FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_TRUECOLOR;
+  
+	info->cmap.len = (info->var.bits_per_pixel == 8) ? 256 : 16;
+      
+	if (info->var.accel_flags) {
+		if (par->accel == ACCEL_NOT_READY || par->accel == ACCEL_USER_DISABLED)
+			par->accel = ACCEL_ACTIVE;
+	}
+	else {
+		if (par->accel == ACCEL_NOT_READY)
+			par->accel = ACCEL_USER_DISABLED;
+	}
+	
+	return 0;
+}
+
+static int
+lxfb_setcolreg(unsigned regno, unsigned red, unsigned green,
+	       unsigned blue, unsigned transp, struct fb_info *info) {
+
+	if ((info->var.bits_per_pixel == 8 && regno > 255) || regno > 15)
+		return 1;
+  
+	switch(info->var.bits_per_pixel) {
+		case 8: {
+			u32 color = ((red & 0xFF00) << 8) | (green & 0xFF00) | ((blue & 0xFF00) >> 8);
+			vg_set_display_palette_entry(regno, color);
+			vg_set_display_palette_entry(regno ^ 0xFF, color ^ 0xFFFFFF);
+		}
+			break;
+
+		case 16:
+			((u32*)info->pseudo_palette)[regno] = (red & 0xF800) |
+				((green & 0xFC00) >> 5) | ((blue & 0xF800) >> 11);
+			break;
+
+		case 32:
+			((u32*)info->pseudo_palette)[regno] =
+				((transp & 0xFF00) <<16)        |
+				((red & 0xFF00) << 8)           |
+				((green & 0xFF00))              |
+				((blue & 0xFF00)>>8);
+			break;
+	}
+  
+	return 0;
+}
+
+static int
+lxfb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info) {
+  
+	u32 offset = 0;
+  
+	if (var->xoffset < 0 || var->xres + var->xoffset > var->xres_virtual)
+		return -EINVAL;
+     
+	if (var->xoffset < 0 || var->yres + var->yoffset > var->yres_virtual)
+		return -EINVAL;
+
+	/* Calculate the fb offset */
+
+	offset = (var->yoffset * vg_get_display_pitch()) + 
+		(var->xoffset * (var->bits_per_pixel >> 3));
+     
+	vg_set_display_offset(offset);  
+	return 0;
+}
+
+static int
+lxfb_blank(int blank_mode, struct fb_info *info) {
+
+#ifdef CONFIG_FB_GEODE_PANEL
+	/* Blank the panel if we have one attached */
+
+	if (active_devices & GEODEFB_PANEL_DEV)
+		df_set_panel_enable( (blank_mode) ? 0 : 1);
+#endif
+  
+	switch(blank_mode) {
+		case VESA_POWERDOWN:
+			df_set_crt_enable(DF_CRT_DISABLE);
+			break;
+
+		case VESA_VSYNC_SUSPEND:
+			df_set_crt_enable(DF_CRT_SUSPEND);
+			break;
+    
+		case VESA_HSYNC_SUSPEND:
+			df_set_crt_enable(DF_CRT_STANDBY);
+			break;
+    
+		default:
+			df_set_crt_enable(DF_CRT_ENABLE);
+			break;
+	}
+
+	return 0;
+}
+
+
+#ifdef CONFIG_FB_GEODE_ACCEL
+
+int lxfb_sync(struct fb_info *info) {
+	struct lxfb_par *par = (struct lxfb_par *) info->par;
+  
+	if (par->accel == ACCEL_ACTIVE)
+		gp_wait_blt_pending();
+
+	return 0;
+}
+#endif
+
+#ifdef CONFIG_FB_GEODE_ACCEL
+void lxfb_imageblit(struct fb_info *, const struct fb_image *);
+void lxfb_copyarea(struct fb_info *, const struct fb_copyarea *);
+void lxfb_fillrect(struct fb_info *, const struct fb_fillrect *);
+#endif
+
+static struct fb_ops lxfb_fb_ops = {
+	owner:          THIS_MODULE,
+
+	fb_setcolreg:   lxfb_setcolreg,
+	fb_check_var:   lxfb_check_var,
+	fb_set_par:     lxfb_set_par, 
+	fb_pan_display: lxfb_pan_display,
+	fb_blank:       lxfb_blank,
+
+#ifdef CONFIG_FB_GEODE_ACCEL
+	fb_fillrect:    lxfb_fillrect,
+	fb_copyarea:    lxfb_copyarea,
+	fb_imageblit:   lxfb_imageblit,
+	fb_sync:        lxfb_sync,
+#else
+	fb_fillrect:    cfb_fillrect,
+	fb_copyarea:    cfb_copyarea,
+	fb_imageblit:   cfb_imageblit,
+#endif
+
+/* 	fb_cursor:      soft_cursor, */
+};
+      
+static int 
+lxfb_mem_init(struct lxfb_par *par) 
+{  
+	int ret;
+  
+	par->fbsize = (maxmem * 1024);
+	if (par->fbsize > cim_get_fb_active())
+		par->fbsize = cim_get_fb_active();
+
+	KWRN("Allocating %dK of framebuffer memory\n", par->fbsize / 1024);
+
+	par->fbphys = cim_get_fb_base();
+	par->fbvirt = cim_get_fb_ptr();
+
+	ret = cim_get_memory("geodefb", "framebuffer", par->fbsize, CIM_F_PUBLIC);
+	if (!ret) return -ENOMEM;
+
+	/* Set up acceleration - if this fails, its not fatal */
+
+#ifdef CONFIG_FB_GEODE_ACCEL
+	if (accel) {
+		par->gpphys = cim_get_cmd_base();
+		par->gpsize = cim_get_cmd_size();
+    
+		if (par->gpphys) 
+			par->accel = ACCEL_NOT_READY;
+	}
+#endif
+  
+	return 0;
+}
+
+static GP_SAVE_RESTORE gpsave;
+static VG_SAVE_RESTORE vgsave;
+static DF_SAVE_RESTORE dfsave;
+
+int lxfb_suspend(struct device *dev, u32 state, u32 level) {
+      	
+/* 	if (level == SUSPEND_POWER_DOWN) { */
+/* #ifdef CONFIG_FB_GEODE_PANEL */
+/* 		if (active_devices & GEODEFB_PANEL_DEV) */
+/* 			df_set_panel_enable(0); */
+/* #endif */
+/* 		df_set_crt_enable(DF_CRT_DISABLE); */
+		
+/* 		gp_save_state(&gpsave); */
+/* 		vg_save_state(&vgsave); */
+/* 		df_save_state(&dfsave); */
+/* 	} */
+
+	return 0;
+}
+
+int lxfb_resume(struct device *dev, u32 level) {
+      	
+/* 	if (level == RESUME_ENABLE) { */
+/* 		vg_restore_state(&vgsave); */
+/* 		gp_restore_state(&gpsave); */
+/* 		df_restore_state(&dfsave); */
+		
+/* 		df_set_crt_enable(DF_CRT_ENABLE); */
+		
+/* #ifdef CONFIG_FB_GEODE_PANEL */
+/* 		if (active_devices & GEODEFB_PANEL_DEV) */
+/* 			df_set_panel_enable(1); */
+/* #endif */
+/* 	} */
+
+	return 0;
+}				
+
+/* static int  */
+/* lxfb_console_notify(struct notifier_block *self, */
+/* 		    unsigned long action, void *data) { */
+
+/* 	struct lxfb_par *par = (struct lxfb_par *) fbinfo->par; */
+
+/* 	if (action == CONSOLE_EVENT_SWITCH_TEXT) { */
+
+/* 		if (par->accel == ACCEL_KERNEL_DISABLED) { */
+/* 			gp_set_frame_buffer_base (par->fbphys, par->fbsize); */
+/* 			gp_set_command_buffer_base(par->gpphys, 0, par->gpsize); */
+      
+/* 			par->accel = ACCEL_ACTIVE; */
+/* 		} */
+/* 	} */
+/* 	else if (action == CONSOLE_EVENT_SWITCH_GRAPHICS) { */
+/* 		if (par->accel == ACCEL_ACTIVE) { */
+/* 			gp_wait_blt_pending(); */
+/* 			par->accel = ACCEL_KERNEL_DISABLED; */
+/* 		} */
+/* 	} */
+
+/* 	return 0; */
+/* } */
+
+/* static struct notifier_block lxfb_console_notifier = { */
+/*         .notifier_call  = lxfb_console_notify, */
+/* }; */
+
+int __init
+lxfb_init(struct device *device)
+{  
+	int ret, parsed = 0;
+	struct platform_device *dev = to_platform_device(device);
+
+	fbinfo = framebuffer_alloc(sizeof(struct lxfb_par), &dev->dev);
+
+	if (!fbinfo) {
+		KERR("Unable to allocatethe framebuffer memory.\n");
+		return -ENOMEM;
+	}
+
+	active_devices = geodefb_get_devices();
+
+	initial_mode.refresh = vfreq;
+	
+	if (vmode[0] != 0) {
+		geodefb_parse_mode(vmode, &initial_mode);
+		parsed = 1;
+	}
+
+#ifdef CONFIG_FB_GEODE_PANEL
+	if (active_devices & GEODEFB_PANEL_DEV) {
+
+		if (flatpanel) {
+			geodefb_get_panel_info(&panel_info);
+			if (!parsed) {
+				initial_mode.xres = panel_info.xres;
+				initial_mode.yres = panel_info.yres;
+			}
+			initial_mode.refresh = panel_info.refresh;
+			KWRN("TFT support enabled.");
+		}	  
+		else
+			active_devices &= ~GEODEFB_PANEL_DEV;
+	}
+#endif
+
+	if (lxfb_mem_init((struct lxfb_par *) fbinfo->par)) {
+		KERR("Unable to initialize the graphics engine.\n");
+		kfree(fbinfo);
+		return -ENODEV;
+	}
+
+	fbinfo->screen_base = ((struct lxfb_par *) fbinfo->par)->fbvirt;
+	fbinfo->fbops = &lxfb_fb_ops;
+	fbinfo->fix = lxfb_fix;
+	fbinfo->pseudo_palette = lxfb_palette;
+ 
+	/* Since we have a nifty screen to screen blit, we use that for
+	   scrolling - look ma, no bus!
+	*/
+
+	fbinfo->flags = LXFB_FBINFO_FLAGS | FBINFO_READS_FAST;  
+
+	ret = lxfb_find_mode(fbinfo->par, &fbinfo->var, &initial_mode);
+
+	if (ret < 0) {
+		KERR("Invalid mode %dx%d@%d-%d\n", initial_mode.xres, initial_mode.yres,
+		     initial_mode.refresh, initial_mode.depth);
+
+		return -EINVAL;
+	}
+
+	KWRN("Initial mode: %dx%d@%d-%d\n", 
+	     initial_mode.xres, initial_mode.yres,
+	     initial_mode.refresh, initial_mode.depth);
+		     
+	fbinfo->var.activate |= FB_ACTIVATE_NOW;
+
+	fb_alloc_cmap(&fbinfo->cmap, 256, 0);
+
+	/* ==== register ==== */
+
+/* 	notifier_chain_register(&console_notifier_list, */
+/* 				&lxfb_console_notifier); */
+
+	if (register_framebuffer(fbinfo) < 0) {
+		framebuffer_release(fbinfo);
+		KERR("Unable to register the framebuffer\n");
+		return -EINVAL;
+	}
+
+	printk(KERN_INFO "%s\n", AMD_VERSION);
+	return 0;
+}
+
+void __exit 
+lxfb_cleanup(void) {
+/* 	notifier_chain_unregister(&console_notifier_list,  */
+/* 				  &lxfb_console_notifier); */
+
+	unregister_framebuffer((struct fb_info *) fbinfo);
+	framebuffer_release(fbinfo);
+}
+
+
diff --git a/drivers/video/geode/geodefb_lx.h b/drivers/video/geode/geodefb_lx.h
new file mode 100644
index 0000000..e4219ea
--- /dev/null
+++ b/drivers/video/geode/geodefb_lx.h
@@ -0,0 +1,60 @@
+/* <LIC_AMD_STD>
+ * Copyright (c) 2004-2005 Advanced Micro Devices, Inc.
+ * 
+ * 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
+ * 
+ * The full GNU General Public License is included in this distribution in the
+ * file called COPYING
+ * </LIC_AMD_STD>  */
+/* <CTL_AMD_STD>
+ * </CTL_AMD_STD>  */
+/* <DOC_AMD_STD>
+ * Geode LX framebuffer header file
+ * </DOC_AMD_STD>  */
+
+#ifndef GEODEFB_LX_H_
+#define GEODEFB_LX_H_
+
+#define KERR(str, args...) printk(KERN_ERR "geodefb-lx: " str, ##args)
+#define KWRN(str, args...) printk(KERN_INFO "geodefb-lx: " str, ##args)
+
+/* bit 0:  acceleration available
+   bit 1:  acceleration active
+   bit 2:  acceleration suspended by kernel
+   bit 3:  acceleration suspended by user
+*/
+
+#define ACCEL_OFF              0x0 /* Accleration not available */
+#define ACCEL_NOT_READY        0x1 /* Acceleration is available but the engine isn't set up yet */
+#define ACCEL_ACTIVE           0x3 /* Accleration is active */
+#define ACCEL_KERNEL_DISABLED  0x5 /* Acceleration has been turned off by the kernel */
+#define ACCEL_USER_DISABLED    0x9 /* Acceleration has been turned off by the user */
+
+#define ACCEL_AVAILABLE_MASK   0x1
+#define ACCEL_ACTIVE_MASK      0x2
+
+struct lxfb_par {
+  int accel;
+  unsigned long fbphys;              /* The physical address of the FB */
+  char *fbvirt;                      /* The virtual address of the FB */
+  int fbsize;                        /* The size of the FB */
+
+  unsigned long gpphys;              /* The physical address of the GP */
+  int gpsize;                        /* The size of the GP */
+
+  int vfreq;
+};
+
+#endif
diff --git a/drivers/video/geode/geodefb_lx_accel.c b/drivers/video/geode/geodefb_lx_accel.c
new file mode 100644
index 0000000..7f06a8f
--- /dev/null
+++ b/drivers/video/geode/geodefb_lx_accel.c
@@ -0,0 +1,168 @@
+/* <LIC_AMD_STD>
+ * Copyright (c) 2004-2005 Advanced Micro Devices, Inc.
+ * 
+ * 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
+ * 
+ * The full GNU General Public License is included in this distribution in the
+ * file called COPYING
+ * </LIC_AMD_STD>  */
+/* <CTL_AMD_STD>
+ * </CTL_AMD_STD>  */
+/* <DOC_AMD_STD>
+ * Geode LX acceleration routines
+ * </DOC_AMD_STD>  */
+
+/* #include <linux/config.h> */
+#include <linux/module.h>
+#include <linux/kernel.h>
+
+#include <cim/cim_rtns.h>
+
+#include "geodefb.h"
+#include "geodefb_lx.h"
+
+extern int lxfb_get_pitch(int, int);
+
+/* Matches ROP_ defines in fb.h */
+static unsigned char lx_rops[] = { 0xF0, 0x55 };
+
+void 
+lxfb_imageblit(struct fb_info *info, const struct fb_image *image) {
+
+  struct lxfb_par *par = (struct lxfb_par *) info->par;  
+  int pitch = lxfb_get_pitch(info->var.xres_virtual, info->var.bits_per_pixel);
+  u32 dst = (image->dy * pitch) + (image->dx * (info->var.bits_per_pixel >> 3));
+
+  if (par->accel != ACCEL_ACTIVE) {
+    cfb_imageblit(info, image);
+    return;
+  }
+
+  if (image->depth == 1) {
+    u32 fg = 0, bg = 0;
+       
+    switch(info->var.bits_per_pixel) {
+    case 8: 
+      bg = image->bg_color;
+      fg = image->fg_color;      
+      break;
+      
+    case 16:
+    case 32:
+      bg = ((u32 *) info->pseudo_palette)[image->bg_color];
+      fg = ((u32 *) info->pseudo_palette)[image->fg_color];
+      break;
+    }
+    
+    gp_declare_blt(0);
+    gp_set_raster_operation(0xCC);
+    gp_set_strides(pitch, 0);    
+    gp_set_mono_source(bg, fg, 0);
+    
+    gp_mono_bitmap_to_screen_blt(dst, 0,
+				 image->width, image->height, 
+				 (unsigned char *) image->data, 
+				 image->width / 8);
+  } else if (image->depth == info->var.bits_per_pixel) {
+
+    gp_declare_blt(0);
+    gp_set_raster_operation(0xCC);
+    gp_set_strides(pitch, 0);    
+
+    gp_color_bitmap_to_screen_blt(dst, 0, image->width, image->height,
+				  (unsigned char *) image->data,
+				  image->width * (image->depth >> 3));    
+  }
+  else {
+    int flags = 0;
+          
+    if (image->depth == 8) {
+      u32 colors[256];
+      memcpy(colors, (u32 *) info->pseudo_palette, 256 * sizeof(u32));
+      
+      gp_program_lut((unsigned long *) colors, 1);
+      flags = CIMGP_BLTFLAGS_PRES_LUT;
+    }
+    
+    gp_declare_blt(flags);
+    gp_set_raster_operation(0xCC);
+    gp_set_strides(pitch, 0);    
+
+    switch(image->depth) {
+    case 8:
+      gp_set_source_format(CIMGP_SOURCE_FMT_8BPP_INDEXED);
+      break;
+    case 16:
+      gp_set_source_format(CIMGP_SOURCE_FMT_0_5_6_5);
+      break;
+    case 32:
+      gp_set_source_format(CIMGP_SOURCE_FMT_8_8_8_8);
+      break;
+    }
+
+    gp_color_convert_blt(dst, 0, image->width, image->height,
+			 (unsigned char *) image->data,
+			 image->width * (image->depth >> 3));
+  }
+}
+
+void 
+lxfb_copyarea(struct fb_info *info, const struct fb_copyarea *area) {
+  
+  struct lxfb_par *par = (struct lxfb_par *) info->par;
+  int pitch = lxfb_get_pitch(info->var.xres_virtual, info->var.bits_per_pixel);
+  int flags = 0;
+
+  u32 src = (area->sy * pitch) + (area->sx * (info->var.bits_per_pixel >> 3));
+  u32 dst = (area->dy * pitch) + (area->dx * (info->var.bits_per_pixel >> 3));
+
+  if (par->accel != ACCEL_ACTIVE) {
+    cfb_copyarea(info, area);
+    return;
+  }
+  
+  gp_declare_blt(0);
+  gp_set_raster_operation(0xCC);
+  gp_set_strides(pitch, pitch);  
+  gp_set_solid_pattern(0);
+  
+  if (area->dx > area->sx) flags |= CIMGP_NEGXDIR;
+  if (area->dy > area->sy) flags |= CIMGP_NEGYDIR;
+
+  gp_screen_to_screen_blt(dst, src, area->width, area->height, flags);    
+}
+  
+void 
+lxfb_fillrect(struct fb_info *info, const struct fb_fillrect *rect) {
+
+  struct lxfb_par *par = (struct lxfb_par *) info->par;  
+  int pitch = lxfb_get_pitch(info->var.xres_virtual, info->var.bits_per_pixel);
+  u32 dst = (rect->dy * pitch) + (rect->dx * (info->var.bits_per_pixel >> 3));
+
+  if (par->accel != ACCEL_ACTIVE) {
+    cfb_fillrect(info, rect);
+    return;
+  }
+
+  gp_declare_blt(0);
+  gp_set_raster_operation(lx_rops[rect->rop]);  
+  
+  if (lx_rops[rect->rop] != 0x55)
+    gp_set_solid_pattern(rect->color);
+
+  gp_set_strides(pitch, 0);
+    
+  gp_pattern_fill(dst, rect->width, rect->height);
+}
diff --git a/drivers/video/geode/geodefb_modes.c b/drivers/video/geode/geodefb_modes.c
new file mode 100644
index 0000000..5f6b729
--- /dev/null
+++ b/drivers/video/geode/geodefb_modes.c
@@ -0,0 +1,110 @@
+/* <LIC_AMD_STD>
+ * Copyright (c) 2004-2005 Advanced Micro Devices, Inc.
+ * 
+ * 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
+ * 
+ * The full GNU General Public License is included in this distribution in the
+ * file called COPYING
+ * </LIC_AMD_STD>  */
+/* <CTL_AMD_STD>
+ * </CTL_AMD_STD>  */
+/* <DOC_AMD_STD>
+ * Geode framebuffer header file
+ * </DOC_AMD_STD>  */
+
+#include <linux/string.h>
+#include "geodefb.h"
+
+void geodefb_parse_mode(const char *string, struct geodefb_mode *mode) {
+  
+  char *next, *ptr = (char *) string;
+  int values[4] = { -1, -1, -1, -1 };
+  int flag = 0;
+
+  while(*ptr) {
+    switch(*ptr) {
+    case 'x':
+      flag = 1;
+      ptr++;
+      break;
+    case '@':
+      flag = 2;
+      ptr++;
+      break;
+    case '-':
+      flag = 3;
+      ptr++;
+      break;
+    case '0'...'9':
+      values[flag] = simple_strtoul(ptr, &next, 0);
+      ptr = next;
+      break;
+    }
+  }
+  
+  if (values[0] != -1) mode->xres = values[0];
+  if (values[1] != -1) mode->yres = values[1];
+  if (values[2] != -1) mode->refresh = values[2];
+  if (values[3] != -1) mode->depth = values[3];
+}
+
+/* from fb.modes:
+   P = 1E12 / (V*F*H)
+   F = 1E12 / (V*P*H)
+
+   where P=pixclock, F=frequency, V=vtotal, H=htotal
+*/
+
+/* We can only use 32 bit integers, so we split 1E12 into something
+   more manageable */
+
+static inline int VAR2FREQ(int htotal, int vtotal, int refresh) {
+	   unsigned long h;
+
+	   h = 1953125000 / htotal;
+	   h = h * 512 / refresh;
+	   return (int) (h / vtotal);
+}
+
+static inline int VAR2HZ(int htotal, int vtotal, int pixclock) {
+	unsigned long v;
+	
+        v = 488281250 / htotal;
+	v = v * 2048 / vtotal;
+	return (int) ((((v * 100) / pixclock) + 50) / 100);
+}
+
+static int HTOTAL(struct fb_var_screeninfo *var) {
+  return (var->left_margin + var->xres + var->right_margin + var->hsync_len);
+}
+
+static int VTOTAL(struct fb_var_screeninfo *var) {
+  return (var->upper_margin + var->yres + var->lower_margin + var->vsync_len);
+}
+
+int geodefb_get_timings(struct fb_var_screeninfo *var, int hz, int flag) {
+  
+  unsigned int htotal = HTOTAL(var);
+  unsigned int vtotal = VTOTAL(var);
+
+  switch(flag) {
+  case FB_HTOTAL: return htotal;
+  case FB_VTOTAL: return vtotal;
+  case FB_HZ:  return VAR2HZ(htotal, vtotal, var->pixclock);
+  case FB_FREQ: return VAR2FREQ(htotal, vtotal, hz);
+  }
+
+  return -1;
+}
diff --git a/include/linux/wm97xx.h b/include/linux/wm97xx.h
new file mode 100644
index 0000000..41fa214
--- /dev/null
+++ b/include/linux/wm97xx.h
@@ -0,0 +1,294 @@
+
+/*
+ * Register bits and API for Wolfson WM97xx series of codecs
+ */
+
+#ifndef _LINUX_WM97XX_H
+#define _LINUX_WM97XX_H
+
+#include <sound/driver.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/ac97_codec.h>
+#include <sound/initval.h>
+#include <linux/types.h>
+#include <linux/list.h>
+#include <linux/input.h>	/* Input device layer */
+
+/*
+ * WM97xx AC97 Touchscreen registers
+ */
+#define AC97_WM97XX_DIGITISER1		0x76
+#define AC97_WM97XX_DIGITISER2		0x78
+#define AC97_WM97XX_DIGITISER_RD 	0x7a
+#define AC97_WM9713_DIG1			0x74
+#define AC97_WM9713_DIG2			AC97_WM97XX_DIGITISER1
+#define AC97_WM9713_DIG3			AC97_WM97XX_DIGITISER2
+
+/*
+ * WM97xx register bits
+ */
+#define WM97XX_POLL			0x8000	/* initiate a polling measurement */
+#define WM97XX_ADCSEL_X		0x1000	/* x coord measurement */
+#define WM97XX_ADCSEL_Y		0x2000	/* y coord measurement */
+#define WM97XX_ADCSEL_PRES	0x3000	/* pressure measurement */
+#define WM97XX_ADCSEL_MASK	0x7000
+#define WM97XX_COO			0x0800	/* enable coordinate mode */
+#define WM97XX_CTC			0x0400	/* enable continuous mode */
+#define WM97XX_CM_RATE_93	0x0000	/* 93.75Hz continuous rate */
+#define WM97XX_CM_RATE_187	0x0100	/* 187.5Hz continuous rate */
+#define WM97XX_CM_RATE_375	0x0200	/* 375Hz continuous rate */
+#define WM97XX_CM_RATE_750	0x0300	/* 750Hz continuous rate */
+#define WM97XX_CM_RATE_8K	0x00f0	/* 8kHz continuous rate */
+#define WM97XX_CM_RATE_12K	0x01f0	/* 12kHz continuous rate */
+#define WM97XX_CM_RATE_24K	0x02f0	/* 24kHz continuous rate */
+#define WM97XX_CM_RATE_48K	0x03f0	/* 48kHz continuous rate */
+#define WM97XX_CM_RATE_MASK	0x03f0
+#define WM97XX_RATE(i)		(((i & 3) << 8) | ((i & 4) ? 0xf0 : 0))
+#define WM97XX_DELAY(i)		((i << 4) & 0x00f0)	/* sample delay times */
+#define WM97XX_DELAY_MASK	0x00f0
+#define WM97XX_SLEN			0x0008	/* slot read back enable */
+#define WM97XX_SLT(i)		((i - 5) & 0x7)	/* touchpanel slot selection (5-11) */
+#define WM97XX_SLT_MASK		0x0007
+#define WM97XX_PRP_DETW		0x4000	/* pen detect on, digitiser off, wake up */
+#define WM97XX_PRP_DET		0x8000	/* pen detect on, digitiser off, no wake up */
+#define WM97XX_PRP_DET_DIG	0xc000	/* pen detect on, digitiser on */
+#define WM97XX_RPR			0x2000	/* wake up on pen down */
+#define WM97XX_PEN_DOWN		0x8000	/* pen is down */
+#define WM97XX_ADCSRC_MASK	0x7000	/* ADC source mask */
+
+#define WM97XX_AUX_ID1		0x8001
+#define WM97XX_AUX_ID2		0x8002
+#define WM97XX_AUX_ID3		0x8003
+#define WM97XX_AUX_ID4		0x8004
+
+
+/* WM9712 Bits */
+#define WM9712_45W			0x1000	/* set for 5-wire touchscreen */
+#define WM9712_PDEN			0x0800	/* measure only when pen down */
+#define WM9712_WAIT			0x0200	/* wait until adc is read before next sample */
+#define WM9712_PIL			0x0100	/* current used for pressure measurement. set 400uA else 200uA */
+#define WM9712_MASK_HI		0x0040	/* hi on mask pin (47) stops conversions */
+#define WM9712_MASK_EDGE	0x0080	/* rising/falling edge on pin delays sample */
+#define	WM9712_MASK_SYNC	0x00c0	/* rising/falling edge on mask initiates sample */
+#define WM9712_RPU(i)		(i&0x3f)	/* internal pull up on pen detect (64k / rpu) */
+#define WM9712_PD(i)		(0x1 << i)	/* power management */
+
+/* WM9712 Registers */
+#define AC97_WM9712_POWER	0x24
+#define AC97_WM9712_REV		0x58
+
+/* WM9705 Bits */
+#define WM9705_PDEN			0x1000	/* measure only when pen is down */
+#define WM9705_PINV			0x0800	/* inverts sense of pen down output */
+#define WM9705_BSEN			0x0400	/* BUSY flag enable, pin47 is 1 when busy */
+#define WM9705_BINV			0x0200	/* invert BUSY (pin47) output */
+#define WM9705_WAIT			0x0100	/* wait until adc is read before next sample */
+#define WM9705_PIL			0x0080	/* current used for pressure measurement. set 400uA else 200uA */
+#define WM9705_PHIZ			0x0040	/* set PHONE and PCBEEP inputs to high impedance */
+#define WM9705_MASK_HI		0x0010	/* hi on mask stops conversions */
+#define WM9705_MASK_EDGE	0x0020	/* rising/falling edge on pin delays sample */
+#define	WM9705_MASK_SYNC	0x0030	/* rising/falling edge on mask initiates sample */
+#define WM9705_PDD(i)		(i & 0x000f)	/* pen detect comparator threshold */
+
+
+/* WM9713 Bits */
+#define WM9713_PDPOL		0x0400	/* Pen down polarity */
+#define WM9713_POLL			0x0200	/* initiate a polling measurement */
+#define WM9713_CTC			0x0100	/* enable continuous mode */
+#define WM9713_ADCSEL_X		0x0002	/* X measurement */
+#define WM9713_ADCSEL_Y		0x0004	/* Y measurement */
+#define WM9713_ADCSEL_PRES	0x0008	/* Pressure measurement */
+#define WM9713_COO			0x0001	/* enable coordinate mode */
+#define WM9713_PDEN			0x0800	/* measure only when pen down */
+#define WM9713_ADCSEL_MASK	0x00fe	/* ADC selection mask */
+#define WM9713_WAIT			0x0200	/* coordinate wait */
+
+/* AUX ADC ID's */
+#define TS_COMP1			0x0
+#define TS_COMP2			0x1
+#define TS_BMON				0x2
+#define TS_WIPER			0x3
+
+/* ID numbers */
+#define WM97XX_ID1			0x574d
+#define WM9712_ID2			0x4c12
+#define WM9705_ID2			0x4c05
+#define WM9713_ID2			0x4c13
+
+/* Codec GPIO's */
+#define WM97XX_MAX_GPIO		16
+#define WM97XX_GPIO_1		(1 << 1)
+#define WM97XX_GPIO_2		(1 << 2)
+#define WM97XX_GPIO_3		(1 << 3)
+#define WM97XX_GPIO_4		(1 << 4)
+#define WM97XX_GPIO_5		(1 << 5)
+#define WM97XX_GPIO_6		(1 << 6)
+#define WM97XX_GPIO_7		(1 << 7)
+#define WM97XX_GPIO_8		(1 << 8)
+#define WM97XX_GPIO_9		(1 << 9)
+#define WM97XX_GPIO_10		(1 << 10)
+#define WM97XX_GPIO_11		(1 << 11)
+#define WM97XX_GPIO_12		(1 << 12)
+#define WM97XX_GPIO_13		(1 << 13)
+#define WM97XX_GPIO_14		(1 << 14)
+#define WM97XX_GPIO_15		(1 << 15)
+
+
+#define AC97_LINK_FRAME		21	/* time in uS for AC97 link frame */
+
+
+/*---------------- Return codes from sample reading functions ---------------*/
+
+/* More data is available; call the sample gathering function again */
+#define RC_AGAIN			0x00000001
+/* The returned sample is valid */
+#define RC_VALID			0x00000002
+/* The pen is up (the first RC_VALID without RC_PENUP means pen is down) */
+#define RC_PENUP			0x00000004
+/* The pen is down (RC_VALID implies RC_PENDOWN, but sometimes it is helpful
+   to tell the handler that the pen is down but we don't know yet his coords,
+   so the handler should not sleep or wait for pendown irq) */
+#define RC_PENDOWN			0x00000008
+
+/* The wm97xx driver provides a private API for writing platform-specific
+ * drivers.
+ */
+
+/* The structure used to return arch specific sampled data into */
+struct wm97xx_data {
+    int x;
+    int y;
+    int p;
+};
+
+/* Codec GPIO status
+ */
+typedef enum {
+    WM97XX_GPIO_HIGH,
+    WM97XX_GPIO_LOW
+} wm97xx_gpio_status_t;
+
+/* Codec GPIO direction
+ */
+typedef enum {
+    WM97XX_GPIO_IN,
+    WM97XX_GPIO_OUT
+} wm97xx_gpio_dir_t;
+
+/* Codec GPIO polarity
+ */
+typedef enum {
+    WM97XX_GPIO_POL_HIGH,
+    WM97XX_GPIO_POL_LOW
+} wm97xx_gpio_pol_t;
+
+/* Codec GPIO sticky
+ */
+typedef enum {
+    WM97XX_GPIO_STICKY,
+    WM97XX_GPIO_NOTSTICKY
+} wm97xx_gpio_sticky_t;
+
+/* Codec GPIO wake
+ */
+typedef enum {
+    WM97XX_GPIO_WAKE,
+    WM97XX_GPIO_NOWAKE
+} wm97xx_gpio_wake_t;
+
+
+/*
+ * Digitiser ioctl commands
+ */
+#define WM97XX_DIG_START	0x1
+#define WM97XX_DIG_STOP		0x2
+#define WM97XX_PHY_INIT		0x3
+#define WM97XX_AUX_PREPARE	0x4
+#define WM97XX_DIG_RESTORE	0x5
+
+struct tslib_dejitter;
+struct wm97xx;
+extern struct wm97xx_codec_drv wm97xx_codec;
+
+/*
+ * Codec driver interface - allows mapping to WM9705/12/13 and newer codecs
+ */
+struct wm97xx_codec_drv {
+	u16 id;
+    char *name;
+	int (*poll_sample) (struct wm97xx *, int adcsel, int *sample);	/* read 1 sample */
+	int (*poll_touch) (struct wm97xx *, struct wm97xx_data *);	/* read X,Y,[P] in poll */
+	int (*digitiser_ioctl) (struct wm97xx *, int cmd);
+	int (*acc_enable) (struct wm97xx *, int enable);
+};
+
+
+/* Machine specific and accelerated touch operations */
+struct wm97xx_mach_ops {
+
+	/* accelerated touch readback - coords are transmited on AC97 link */
+	int acc_enabled;
+    void (*acc_pen_up) (struct wm97xx *);
+    int (*acc_pen_down) (struct wm97xx *);
+    int (*acc_startup) (struct wm97xx *);
+    void (*acc_shutdown) (struct wm97xx *);
+
+    /* pre and post sample - can be used to minimise any analog noise */
+    void (*pre_sample) (int);  /* function to run before sampling */
+    void (*post_sample) (int);  /* function to run after sampling */
+};
+
+struct wm97xx {
+	u16 dig[3], id, gpio[6], misc;	/* Cached codec registers */
+	u16 dig_save[3];		/* saved during aux reading */
+	struct wm97xx_codec_drv *codec;	/* attached codec driver*/
+	struct input_dev* input_dev;	/* touchscreen input device */
+	ac97_t *ac97;			/* ALSA codec access */
+	struct device *dev;		/* ALSA device */
+    struct device *battery_dev;
+    struct device *touch_dev;
+    struct wm97xx_mach_ops *mach_ops;
+    struct mutex codec_mutex;
+	struct completion ts_init;
+	struct completion ts_exit;
+	struct task_struct *ts_task;
+	unsigned int pen_irq;	/* Pen IRQ number in use */
+	wait_queue_head_t pen_irq_wait;	/* Pen IRQ wait queue */
+	struct workqueue_struct *pen_irq_workq;
+	struct work_struct pen_event_work;
+	u16 acc_slot; /* AC97 slot used for acc touch data */
+	u16 acc_rate; /* acc touch data rate */
+	unsigned int ts_use_count;
+	unsigned pen_is_down:1;	/* Pen is down */
+	unsigned aux_waiting:1;	/* aux measurement waiting */
+	unsigned pen_probably_down:1;	/* used in polling mode */
+
+	struct tslib_dejitter *dejitter;
+};
+
+/* Codec GPIO access (not supported on WM9705)
+ * This can be used to set/get codec GPIO and Virtual GPIO status.
+ */
+wm97xx_gpio_status_t wm97xx_get_gpio(struct wm97xx *wm, u32 gpio);
+void wm97xx_set_gpio(struct wm97xx *wm, u32 gpio,
+			  wm97xx_gpio_status_t status);
+void wm97xx_config_gpio(struct wm97xx *wm, u32 gpio,
+				     wm97xx_gpio_dir_t dir,
+				     wm97xx_gpio_pol_t pol,
+				     wm97xx_gpio_sticky_t sticky,
+				     wm97xx_gpio_wake_t wake);
+
+/* codec AC97 IO access */
+int wm97xx_reg_read(struct wm97xx *wm, u16 reg);
+void wm97xx_reg_write(struct wm97xx *wm, u16 reg, u16 val);
+
+/* aux adc readback */
+int wm97xx_read_aux_adc(struct wm97xx *wm, u16 adcsel);
+
+/* machine ops */
+int wm97xx_register_mach_ops(struct wm97xx *, struct wm97xx_mach_ops *);
+void wm97xx_unregister_mach_ops(struct wm97xx *);
+
+extern struct bus_type wm97xx_bus_type;
+#endif
diff --git a/lib/Kconfig b/lib/Kconfig
index 9b03581..ce7dfc7 100644
--- a/lib/Kconfig
+++ b/lib/Kconfig
@@ -47,6 +47,16 @@ config AUDIT_GENERIC
 	depends on AUDIT && !AUDIT_ARCH
 	default y
 
+config CIMARRON
+	tristate "AMD LX graphics abstraction layer (Cimarron)"
+	depends on MGEODE_LX
+	default n
+	help
+	  This option is provided for the case where no in-kernel-tree
+	  modules require the AMD LX graphics HAL, but a module built
+	  ouside of the kernel does.
+
+
 #
 # compression support is select'ed if needed
 #
diff --git a/lib/Makefile b/lib/Makefile
index 77b4bad..e342b14 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -47,6 +47,7 @@ obj-$(CONFIG_GENERIC_ALLOCATOR) += genalloc.o
 obj-$(CONFIG_ZLIB_INFLATE) += zlib_inflate/
 obj-$(CONFIG_ZLIB_DEFLATE) += zlib_deflate/
 obj-$(CONFIG_REED_SOLOMON) += reed_solomon/
+obj-$(CONFIG_CIMARRON) += cimarron/
 
 obj-$(CONFIG_TEXTSEARCH) += textsearch.o
 obj-$(CONFIG_TEXTSEARCH_KMP) += ts_kmp.o
diff --git a/lib/cimarron/Makefile b/lib/cimarron/Makefile
new file mode 100644
index 0000000..96d836b
--- /dev/null
+++ b/lib/cimarron/Makefile
@@ -0,0 +1,5 @@
+EXTRA_CFLAGS += -Ilib/cimarron/cim -DREAL_SILICON 
+
+obj-$(CONFIG_CIMARRON) := cimarron.o
+cimarron-objs := cim_mod.o cim_dev.o cim_mem.o cimapi.o
+
diff --git a/lib/cimarron/build_num.h b/lib/cimarron/build_num.h
new file mode 100644
index 0000000..95a6e1c
--- /dev/null
+++ b/lib/cimarron/build_num.h
@@ -0,0 +1,36 @@
+#ifndef BUILD_NUM_H
+#define BUILD_NUM_H
+
+#ifdef AMD_BUILDNUM_DEFINED
+#error "Caution:  You have muliple version files in your path.  Please correct this."
+#endif
+
+#define AMD_BUILDNUM_DEFINED
+
+/* Define the following for your driver */
+
+#define _NAME "AMD LX Cimarron Support Module"
+#define _MAJOR 01
+#define _MINOR 03
+
+/* This defines the current buildlevel and revision of the code */
+#define _BL        01
+#define _BLREV     00
+
+#ifdef _BLREV
+#define _BUILDLEVEL _x(_BL)_x(_BLREV)
+#else
+#define _BUILDLEVEL _x(_BL)
+#endif
+
+/* Use this macro to get the version string */
+
+#define _VERSION_NUMBER _x(_MAJOR) "." _x(_MINOR) "." _BUILDLEVEL
+#define AMD_VERSION _NAME " " _VERSION_NUMBER
+
+/* Syntatic sugar for use above - you probably don't have to touch this */
+
+#define _x(s) _s(s)
+#define _s(s) #s
+
+#endif
diff --git a/lib/cimarron/cim/cim_defs.h b/lib/cimarron/cim/cim_defs.h
new file mode 100644
index 0000000..a1efc51
--- /dev/null
+++ b/lib/cimarron/cim/cim_defs.h
@@ -0,0 +1,717 @@
+ /*
+  * <LIC_AMD_STD>
+  * Copyright (C) 2005 Advanced Micro Devices, Inc.  All Rights Reserved.
+  * </LIC_AMD_STD>
+  * 
+  * <CTL_AMD_STD>
+  * </CTL_AMD_STD>
+  * 
+  * <DOC_AMD_STD>
+  * Cimarron hardware access macros.
+  * </DOC_AMD_STD>
+  * 
+  */
+
+#ifndef _cim_defs_h
+#define _cim_defs_h
+
+/*-----------------------------------------*/
+/*          MEMORY ACCESS MACROS           */
+/*-----------------------------------------*/
+
+#ifndef CIMARRON_EXCLUDE_REGISTER_ACCESS_MACROS
+
+#define READ_GP32(offset) \
+    (*(volatile unsigned long *)(cim_gp_ptr + (offset)))
+
+#define READ_REG32(offset) \
+    (*(volatile unsigned long *)(cim_vg_ptr + (offset)))
+
+#define READ_FB32(offset) \
+    (*(volatile unsigned long *)(cim_fb_ptr + (offset)))
+
+#define WRITE_GP32(offset, value) \
+	(*(volatile unsigned long *)(cim_gp_ptr + (offset))) = (value)
+
+#define WRITE_REG32(offset, value) \
+	(*(volatile unsigned long *)(cim_vg_ptr + (offset))) = (value)
+
+#define WRITE_COMMAND32(offset, value) \
+	(*(unsigned long *)(cim_cmd_ptr + (offset))) = (value)
+
+#define WRITE_COMMAND8(offset, value) \
+	(*(unsigned char *)(cim_cmd_ptr + (offset))) = (value)
+
+#define WRITE_FB32(offset, value) \
+	(*(unsigned long *)(cim_fb_ptr + (offset))) = (value)
+
+#define READ_VID32(offset) \
+    (*(volatile unsigned long *)(cim_vid_ptr + (offset)))
+
+#define WRITE_VID32(offset, value) \
+	(*(volatile unsigned long *)(cim_vid_ptr + (offset))) = (value)
+
+#define READ_VIP32(offset) \
+    (*(volatile unsigned long *)(cim_vip_ptr + (offset)))
+
+#define WRITE_VIP32(offset, value) \
+	(*(volatile unsigned long *)(cim_vip_ptr + (offset))) = (value)
+
+#define READ_VOP32(offset) \
+    (*(volatile unsigned long *)(cim_vid_ptr + (offset)))
+
+#define WRITE_VOP32(offset, value) \
+	(*(volatile unsigned long *)(cim_vid_ptr + (offset))) = (value)
+
+#endif
+
+/*-----------------------------------------*/
+/*            GP POLLING MACROS            */
+/*-----------------------------------------*/
+
+#define GP3_WAIT_WRAP(variable) \
+	while(((variable = READ_GP32 (GP3_CMD_READ)) > gp3_cmd_current) || \
+           (variable <= (gp3_cmd_top + GP3_BLT_COMMAND_SIZE + GP3_BLT_COMMAND_SIZE + 96)))
+
+#define GP3_WAIT_PRIMITIVE(variable) \
+	while (((variable = READ_GP32 (GP3_CMD_READ)) > gp3_cmd_current) && \
+            (variable <= (gp3_cmd_next + 96)))
+
+#define GP3_WAIT_BUSY \
+	while(READ_GP32 (GP3_BLT_STATUS) & GP3_BS_BLT_BUSY)
+
+#define GP3_WAIT_PENDING \
+	while(READ_GP32 (GP3_BLT_STATUS) & GP3_BS_BLT_PENDING)
+
+/*-----------------------------------------------------------------*/
+/* MSR MACROS                                                      */
+/* These macros facilitate interaction with the model specific     */
+/* registers in GeodeLX.  There are two included methods, direct   */
+/* access using the rdmsr and wrmsr opcodes and an indirect method */
+/* using VSAII.                                                    */
+/*-----------------------------------------------------------------*/
+
+#ifdef CIMARRON_INCLUDE_MSR_MACROS
+
+#if CIMARRON_MSR_DIRECT_ASM
+
+/*-----------------------------------------------------------------
+ * MSR_READ
+ * Read the contents of a 64 bit MSR into a data structure
+ *-----------------------------------------------------------------*/
+
+#define MSR_READ(msr_reg, device_add, data64_ptr)                                   \
+{                                                                                   \
+	unsigned long msr_add = (unsigned long)(msr_reg) | (unsigned long)(device_add); \
+	unsigned long data_high, data_low;                                              \
+	_asm { mov ecx, msr_add   }                                                     \
+	_asm { rdmsr              }                                                     \
+	_asm { mov data_high, edx }                                                     \
+	_asm { mov data_low,  eax }                                                     \
+	                                                                                \
+	((Q_WORD *)(data64_ptr))->high = data_high;                                     \
+	((Q_WORD *)(data64_ptr))->low  = data_low;                                      \
+}
+
+/*-----------------------------------------------------------------
+ * MSR_WRITE
+ * Write the contents of a 64 bit data structure to a MSR.
+ *-----------------------------------------------------------------*/
+
+#define MSR_WRITE(msr_reg, device_add, data64_ptr)                                  \
+{                                                                                   \
+	unsigned long msr_add = (unsigned long)(msr_reg) | (unsigned long)(device_add); \
+	unsigned long data_high, data_low;                                              \
+	                                                                                \
+	data_high = ((Q_WORD *)(data64_ptr))->high;                                     \
+	data_low  = ((Q_WORD *)(data64_ptr))->low;                                      \
+		                                                                            \
+	_asm { mov ecx, msr_add   }                                                     \
+	_asm { mov edx, data_high }                                                     \
+	_asm { mov eax, data_low  }                                                     \
+	_asm { wrmsr              }                                                     \
+}
+
+#elif CIMARRON_MSR_VSA_IO
+
+/*-----------------------------------------------------------------
+ * MSR_READ
+ * Read the contents of a 64 bit MSR into a data structure
+ *-----------------------------------------------------------------*/
+
+#define MSR_READ(msr_reg, device_add, data64_ptr)                                   \
+{                                                                                   \
+	unsigned long msr_add = (unsigned long)(msr_reg) | (unsigned long)(device_add); \
+	unsigned long data_high, data_low;                                              \
+		                                                                            \
+	_asm { mov    dx,  0x0AC1C      } 	                                            \
+	_asm { mov    eax, 0x0FC530007  }                                               \
+	_asm { out    dx, eax           }                                               \
+		                                                                            \
+	_asm { add    dl, 2             }                                               \
+	_asm { mov    ecx, msr_add      }                                               \
+	_asm { in     ax, dx            }                                               \
+	_asm { mov    data_high, edx    }                                               \
+	_asm { mov    data_low, eax     }                                               \
+		                                                                            \
+	((Q_WORD *)(data64_ptr))->high = data_high;                                     \
+	((Q_WORD *)(data64_ptr))->low  = data_low;                                      \
+}
+
+/*-----------------------------------------------------------------
+ * MSR_WRITE
+ * Write the contents of a 64 bit data structure to a MSR.
+ *-----------------------------------------------------------------*/
+
+#define MSR_WRITE(msr_reg, device_add, data64_ptr)                                  \
+{                                                                                   \
+	unsigned long msr_add = (unsigned long)(msr_reg) | (unsigned long)(device_add); \
+	unsigned long data_high, data_low;                                              \
+		                                                                            \
+	data_high = ((Q_WORD *)(data64_ptr))->high;                                     \
+	data_low  = ((Q_WORD *)(data64_ptr))->low;                                      \
+		                                                                            \
+	_asm { mov    dx,  0x0AC1C      } 	                                            \
+	_asm { mov    eax, 0x0FC530007  }                                               \
+	_asm { out    dx, eax           }                                               \
+		                                                                            \
+	_asm { add    dl, 2             }                                               \
+	_asm { mov    ecx, msr_add      }                                               \
+	_asm { mov    ebx, data_high    }                                               \
+	_asm { mov    eax, data_low }                                                   \
+		                                                                            \
+	_asm { mov    esi, 0 }                                                          \
+	_asm { mov    edi, 0 }                                                          \
+	_asm { out    dx, ax }                                                          \
+}
+
+#elif CIMARRON_MSR_ABSTRACTED_ASM
+
+/*-----------------------------------------------------------------
+ * MSR_READ
+ * Read the contents of a 64 bit MSR into a data structure
+ *-----------------------------------------------------------------*/
+
+#define MSR_READ(msr,adr,val)                   \
+     __asm__ __volatile__(                      \
+        " mov $0x0AC1C, %%edx\n"                \
+        " mov $0xFC530007, %%eax\n"             \
+        " out %%eax,%%dx\n"                     \
+        " add $2,%%dl\n"                        \
+        " in %%dx, %%ax"                        \
+        : "=a" ((val)->low), "=d" ((val)->high) \
+        : "c" (msr | adr))
+
+/*-----------------------------------------------------------------
+ * MSR_WRITE
+ * Write the contents of a 64 bit data structure to a MSR.
+ *-----------------------------------------------------------------*/
+
+#define MSR_WRITE(msr,adr,val)                                      \
+     { int d0, d1, d2, d3, d4;                                      \
+     __asm__ __volatile__(                                          \
+        " mov $0x0AC1C, %%edx\n"                                    \
+        " mov $0xFC530007, %%eax\n"                                 \
+        " out %%eax,%%dx\n"                                         \
+        " add $2,%%dl\n"                                            \
+        " mov %5, %4\n"                                             \
+        " mov 0(%6), %1\n"                                          \
+        " mov 4(%6), %0\n"                                          \
+        " xor %3, %3\n"                                             \
+        " xor %2, %2\n"                                             \
+        " out %%ax, %%dx"                                           \
+        : "=a" (d0), "=b" (d1), "=&D" (d2), "=&S" (d3), "=c" (d4)   \
+        : "2" (msr | adr), "3" (val));                              \
+     }
+
+#elif CIMARRON_MSR_KERNEL_ROUTINE
+
+#include "asm/msr.h"
+
+/*-----------------------------------------------------------------
+ * MSR_READ
+ * Read the contents of a 64 bit MSR into a data structure
+ *-----------------------------------------------------------------*/
+
+#define MSR_READ(msr_reg, device_add, data64_ptr)                                   \
+{                                                                                   \
+    unsigned long addr, val1, val2;                                                 \
+                                                                                    \
+	addr = device_add | msr_reg;                                                    \
+	rdmsr (addr, val1, val2);                                                       \
+                                                                                    \
+	((Q_WORD *)(data64_ptr))->high = val2;                                          \
+	((Q_WORD *)(data64_ptr))->low  = val1;	                                        \
+}
+
+/*-----------------------------------------------------------------
+ * MSR_WRITE
+ * Read the contents of a 64 bit data structure to a MSR.
+ *-----------------------------------------------------------------*/
+
+#define MSR_WRITE(msr_reg, device_add, data64_ptr)                                  \
+{                                                                                   \
+	unsigned long addr, val1, val2;                                                 \
+                                                                                    \
+	val2 = ((Q_WORD *)(data64_ptr))->high;                                          \
+	val1 = ((Q_WORD *)(data64_ptr))->low;                                           \
+                                                                                    \
+	addr = (device_add & 0xFFFF0000) | (unsigned long)msr_reg;                      \
+	wrmsr(addr, val1, val2);                                                        \
+}
+
+#endif
+
+#endif /* #ifdef CIMARRON_INCLUDE_MSR_MACROS */
+
+/*-----------------------------------------------------------------*/
+/* STRING MACROS                                                   */
+/* These macros are included to facilitate the optimization of     */
+/* routines that write or copy large amounts of data.  Two vesions */
+/* of these macros are included.  One is intended for operating    */
+/* systems that allow the use of inline assembly, while the other  */
+/* is a pure C implementation for stricter operating systems.      */
+/*-----------------------------------------------------------------*/
+
+#ifdef CIMARRON_INCLUDE_STRING_MACROS
+
+#if CIMARRON_OPTIMIZE_ASSEMBLY
+
+/*-----------------------------------------------------------------
+ * WRITE_COMMAND_STRING32   
+ * Write a series of DWORDs to the current command buffer offset  
+ *-----------------------------------------------------------------*/
+
+#define WRITE_COMMAND_STRING32(offset, dataptr, dataoffset, dword_count) \
+{                                                                        \
+	_asm { cld                           }                               \
+	_asm { mov edi, cim_cmd_ptr          }                               \
+	_asm { add edi, offset               }                               \
+	_asm { mov esi, dataptr              }                               \
+	_asm { add esi, dataoffset           }                               \
+	_asm { mov ecx, dword_count          }                               \
+	_asm { rep movsd                     }                               \
+}
+
+/*-----------------------------------------------------------------
+ * WRITE_FB_STRING32
+ * Write a series of DWORDS to video memory.
+ *-----------------------------------------------------------------*/
+
+#define WRITE_FB_STRING32(offset, dataptr, dword_count)                  \
+{                                                                        \
+    unsigned long temp = (unsigned long)(dataptr);                       \
+	_asm { cld                           }                               \
+	_asm { mov edi, cim_fb_ptr           }                               \
+	_asm { add edi, offset               }                               \
+	_asm { mov esi, temp                 }                               \
+	_asm { mov ecx, dword_count          }                               \
+	_asm { rep movsd                     }                               \
+}
+
+/*-----------------------------------------------------------------
+ * WRITE_FB_CONSTANT
+ * Write a constant DWORD to multiple video memory addresses
+ *-----------------------------------------------------------------*/
+
+#define WRITE_FB_CONSTANT(offset, value, dword_count)                    \
+{                                                                        \
+	unsigned long outptr = (unsigned long)cim_fb_ptr + offset;           \
+	unsigned long dwords = dword_count;                                  \
+	_asm { cld                           }                               \
+	_asm { mov edi, outptr               }                               \
+	_asm { mov eax, value                }                               \
+	_asm { mov ecx, dwords               }                               \
+	_asm { rep stosd                     }                               \
+}
+
+/*-----------------------------------------------------------------
+ * WRITE_HOST_SOURCE_STRING32
+ * Write a series of DWORDs to the GP host source register
+ *-----------------------------------------------------------------*/
+
+#define WRITE_HOST_SOURCE_STRING32(dataptr, dataoffset, dword_count)     \
+{                                                                        \
+	_asm { cld                           }                               \
+	_asm { mov edi, cim_gp_ptr           }                               \
+	_asm { add edi, GP3_HST_SRC_RANGE    }                               \
+	_asm { mov esi, dataptr              }                               \
+	_asm { add esi, dataoffset           }                               \
+	_asm { mov ecx, dword_count          }                               \
+	_asm { rep movsd                     }                               \
+}
+
+#elif CIMARRON_OPTIMIZE_FORLOOP
+
+/*-----------------------------------------------------------------
+ * WRITE_COMMAND_STRING32   
+ * Write a series of DWORDs to the current command buffer offset  
+ *-----------------------------------------------------------------*/
+
+#define WRITE_COMMAND_STRING32(offset, dataptr, dataoffset, dword_count)                   \
+{                                                                                          \
+	unsigned long i;                                                                       \
+	unsigned long tempdata = (unsigned long)dataptr + (dataoffset);                        \
+	unsigned long byte_off = 0;                                                            \
+	for (i = 0; i < dword_count; i++, byte_off += 4)                                       \
+		WRITE_COMMAND32 ((offset) + byte_off, *((unsigned long *)(tempdata + byte_off)));  \
+}
+
+/*-----------------------------------------------------------------
+ * WRITE_FB_STRING32
+ * Write a series of DWORDS to video memory.
+ *-----------------------------------------------------------------*/
+
+#define WRITE_FB_STRING32(offset, dataptr, dword_count)                               \
+{                                                                                     \
+	unsigned long i;                                                                  \
+	unsigned long tempdata = (unsigned long)dataptr;                                  \
+	unsigned long byte_off = 0;                                                       \
+	for (i = 0; i < dword_count; i++, byte_off += 4)                                  \
+		WRITE_FB32 ((offset) + byte_off, *((unsigned long *)(tempdata + byte_off)));  \
+}
+
+/*-----------------------------------------------------------------
+ * WRITE_FB_CONSTANT
+ * Write a constant DWORD to multiple video memory addresses
+ *-----------------------------------------------------------------*/
+
+#define WRITE_FB_CONSTANT(offset, value, dword_count)                                        \
+{                                                                                            \
+	unsigned long i;                                                                         \
+	unsigned long tempoffset = offset;                                                       \
+	for (i = 0; i < dword_count; i++, tempoffset += 4)                                       \
+		WRITE_FB32 (tempoffset, value);                                                      \
+}
+
+/*-----------------------------------------------------------------
+ * WRITE_HOST_SOURCE_STRING32
+ * Write a series of DWORDs to the GP host source register
+ *-----------------------------------------------------------------*/
+
+#define WRITE_HOST_SOURCE_STRING32(dataptr, dataoffset, dword_count)                           \
+{                                                                                              \
+	unsigned long i;                                                                           \
+	unsigned long tempdata = (unsigned long)dataptr + (dataoffset);                            \
+	unsigned long byte_off = 0;                                                                \
+	for (i = 0; i < dword_count; i++, byte_off += 4)                                           \
+		WRITE_GP32 (byte_off + GP3_HST_SRC_RANGE, *((unsigned long *)(tempdata + byte_off)));  \
+}
+
+#elif CIMARRON_OPTIMIZE_ABSTRACTED_ASM
+
+#define move_dw(d,s,n)                                  \
+  __asm__ __volatile__(                                 \
+  " rep\n"                                              \
+  " movsl\n"                                            \
+  : "=&c" (d0), "=&S" (d1), "=&D" (d2)                  \
+  : "0" (n), "1" ((const char *)s), "2" ((char *)d)     \
+  : "memory")
+
+/*-----------------------------------------------------------------
+ * WRITE_COMMAND_STRING32   
+ * Write a series of DWORDs to the current command buffer offset  
+ *-----------------------------------------------------------------*/
+
+#define WRITE_COMMAND_STRING32(offset, dataptr, dataoffset, dword_count) \
+{                                                                        \
+    int d0, d1, d2;                                                      \
+    move_dw (cim_cmd_ptr+ ((unsigned long)(offset)),                     \
+        ((unsigned long)(dataptr)+(dataoffset)),                         \
+        dword_count);                                                    \
+}
+
+/*-----------------------------------------------------------------
+ * WRITE_FB_STRING32
+ * Write a series of DWORDS to video memory.
+ *-----------------------------------------------------------------*/
+
+#define WRITE_FB_STRING32(offset, dataptr, dword_count)                               \
+{                                                                                     \
+	unsigned long i;                                                                  \
+	unsigned long tempdata = (unsigned long)dataptr;                                  \
+	unsigned long byte_off = 0;                                                       \
+	for (i = 0; i < dword_count; i++, byte_off += 4)                                  \
+		WRITE_FB32 ((offset) + byte_off, *((unsigned long *)(tempdata + byte_off)));  \
+}
+
+/*-----------------------------------------------------------------
+ * WRITE_FB_CONSTANT
+ * Write a constant DWORD to multiple video memory addresses
+ *-----------------------------------------------------------------*/
+
+#define WRITE_FB_CONSTANT(offset, value, dword_count)                                        \
+{                                                                                            \
+	unsigned long i;                                                                         \
+	unsigned long tempoffset = offset;                                                       \
+	for (i = 0; i < dword_count; i++, tempoffset += 4)                                       \
+		WRITE_FB32 (tempoffset, value);                                                      \
+}
+
+/*-----------------------------------------------------------------
+ * WRITE_HOST_SOURCE_STRING32
+ * Write a series of DWORDs to the GP host source register
+ *-----------------------------------------------------------------*/
+
+#define WRITE_HOST_SOURCE_STRING32(dataptr, dataoffset, dword_count)                           \
+{                                                                                              \
+	unsigned long i;                                                                           \
+	unsigned long tempdata = (unsigned long)dataptr + (dataoffset);                            \
+	unsigned long byte_off = 0;                                                                \
+	for (i = 0; i < dword_count; i++, byte_off += 4)                                           \
+		WRITE_GP32 (byte_off + GP3_HST_SRC_RANGE, *((unsigned long *)(tempdata + byte_off)));  \
+}
+
+#endif
+
+#endif /* #ifdef CIMARRON_INCLUDE_STRING_MACROS */
+
+/*-----------------------------------------------------------------
+ * WRITE_COMMAND_STRING8
+ * Write a series of bytes to the current command buffer offset  
+ *-----------------------------------------------------------------*/
+
+#define WRITE_COMMAND_STRING8(offset, dataptr, dataoffset, byte_count)   \
+{                                                                        \
+	unsigned long i;                                                     \
+	unsigned long array = (unsigned long)dataptr + (dataoffset);         \
+	for (i = 0; i < byte_count; i++)                                     \
+		WRITE_COMMAND8 ((offset) + i, *((unsigned char *)(array + i)));  \
+}
+
+/*-----------------------------------------------------------------
+ * WRITE_HOST_SOURCE_STRING8
+ * Write a series of bytes to the host source register  
+ *-----------------------------------------------------------------*/
+
+#define WRITE_HOST_SOURCE_STRING8(dataptr, dataoffset, byte_count)                          \
+{                                                                                           \
+	unsigned long temp1 = (unsigned long)dataptr + (dataoffset);                            \
+	unsigned long temp2 = 0;                                                                \
+	unsigned long shift = 0;                                                                \
+	unsigned long counter;                                                                  \
+    if (byte_count)                                                                         \
+    {                                                                                       \
+        for (counter = 0; counter < byte_count; counter++)                                  \
+	    {                                                                                   \
+		    temp2 |= ((unsigned long)(*((unsigned char *)(temp1 + counter)))) << shift;     \
+		    shift += 8;                                                                     \
+	    }                                                                                   \
+	    WRITE_GP32 (GP3_HST_SRC, temp2);                                                    \
+    }                                                                                       \
+}
+
+/*-----------------------------------------*/
+/*          CUSTOM STRING MACROS           */
+/*-----------------------------------------*/
+
+#ifndef CIMARRON_EXCLUDE_CUSTOM_MACROS
+
+#define WRITE_CUSTOM_COMMAND_STRING32 WRITE_COMMAND_STRING32
+#define WRITE_CUSTOM_COMMAND_STRING8  WRITE_COMMAND_STRING8
+
+#endif
+
+/*-----------------------------------------*/
+/*             IO ACCESS MACROS            */
+/*-----------------------------------------*/
+
+#ifdef CIMARRON_INCLUDE_IO_MACROS
+
+#if CIMARRON_IO_DIRECT_ACCESS
+
+/*-------------------------------------------
+ * OUTD
+ * Writes one DWORD to a single I/O address.
+ *-------------------------------------------*/
+
+#define OUTD(port, data) cim_outd(port, data)
+void cim_outd (unsigned short port, unsigned long data)
+{
+	_asm {
+		pushf
+		mov     eax, data
+		mov     dx, port
+		out     dx, eax
+		popf
+	}
+}
+
+/*-------------------------------------------
+ * IND
+ * Reads one DWORD from a single I/O address.
+ *-------------------------------------------*/
+
+#define IND(port) cim_ind(port)
+unsigned long cim_ind (unsigned short port)
+{
+	unsigned long data;
+	_asm {
+		pushf
+		mov     dx, port
+		in      eax, dx
+		mov     data, eax
+		popf
+	}
+	return data;
+}
+
+/*-------------------------------------------
+ * OUTW
+ * Writes one WORD to a single I/O address.
+ *-------------------------------------------*/
+
+#define OUTW(port, data) cim_outw(port, data)
+void cim_outw (unsigned short port, unsigned short data)
+{
+	_asm {
+		pushf
+		mov     ax, data
+		mov     dx, port
+		out     dx, ax
+		popf
+	}
+}
+
+/*-------------------------------------------
+ * INW
+ * Reads one WORD from a single I/O address.
+ *-------------------------------------------*/
+
+#define INW(port) cim_inw(port)
+unsigned short cim_inw (unsigned short port)
+{
+	unsigned short data;
+	_asm {
+		pushf
+		mov     dx, port
+		in      ax, dx
+		mov     data, ax
+		popf
+	}
+	return data;
+}
+
+/*-------------------------------------------
+ * OUTB
+ * Writes one BYTE to a single I/O address.
+ *-------------------------------------------*/
+
+#define OUTB(port, data) cim_outb(port, data)
+void cim_outb (unsigned short port, unsigned char data)
+{
+	_asm {
+		pushf
+		mov     al, data
+		mov     dx, port
+		out     dx, al
+		popf
+	}
+}
+
+/*-------------------------------------------
+ * INB
+ * Reads one BYTE from a single I/O address.
+ *-------------------------------------------*/
+
+#define INB(port) cim_inb(port)
+unsigned char cim_inb (unsigned short port)
+{
+	unsigned char data;
+	_asm {
+		pushf
+		mov     dx, port
+		in      al, dx
+		mov     data, al
+		popf
+	}
+	return data;
+}
+
+#elif CIMARRON_IO_ABSTRACTED_ASM
+
+/*-------------------------------------------
+ * OUTD
+ * Writes one DWORD to a single I/O address.
+ *-------------------------------------------*/
+
+#define OUTD(port, data) cim_outd(port, data)
+void cim_outd (unsigned short port, unsigned long data);
+void cim_outd (unsigned short port, unsigned long data)
+{
+	__asm__ __volatile__ ("outl %0,%w1" : : "a" (data), "Nd" (port));
+}
+
+/*-------------------------------------------
+ * IND
+ * Reads one DWORD from a single I/O address.
+ *-------------------------------------------*/
+
+#define IND(port) cim_ind(port)
+unsigned long cim_ind (unsigned short port);
+unsigned long cim_ind (unsigned short port)
+{
+	unsigned long value;
+    __asm__ __volatile__ ("inl %w1,%0" : "=a" (value) : "Nd" (port) );
+
+    return value;
+}
+
+/*-------------------------------------------
+ * OUTW
+ * Writes one WORD to a single I/O address.
+ *-------------------------------------------*/
+
+#define OUTW(port, data) cim_outw(port, data)
+void cim_outw (unsigned short port, unsigned short data);
+void cim_outw (unsigned short port, unsigned short data)
+{
+	__asm__ volatile ("out %0,%1" : : "a" (data),"d" (port));
+}
+
+/*-------------------------------------------
+ * INW
+ * Reads one WORD from a single I/O address.
+ *-------------------------------------------*/
+
+#define INW(port) cim_inw(port)
+unsigned short cim_inw (unsigned short port);
+unsigned short cim_inw (unsigned short port)
+{
+	unsigned short value;
+    __asm__ volatile ("in %1,%0" : "=a" (value) : "d" (port));
+    return value;
+}
+
+/*-------------------------------------------
+ * INB
+ * Reads one BYTE from a single I/O address.
+ *-------------------------------------------*/
+
+#define INB(port) cim_inb(port)
+unsigned char cim_inb(unsigned short port);
+unsigned char cim_inb(unsigned short port)
+{
+   unsigned char value;
+   __asm__ volatile ("inb %1,%0":"=a" (value):"d"(port));
+
+   return value;
+}
+
+/*-------------------------------------------
+ * OUTB
+ * Writes one BYTE to a single I/O address.
+ *-------------------------------------------*/
+
+#define OUTB(port) cim_outb(port)
+void cim_outb(unsigned short port, unsigned char data);
+void cim_outb(unsigned short port, unsigned char data)
+{
+   __asm__ volatile ("outb %0,%1"::"a" (data), "d"(port));
+}
+
+#endif
+
+#endif /* CIMARRON_INCLUDE_IO_MACROS */
+
+#endif
diff --git a/lib/cimarron/cim/cim_df.c b/lib/cimarron/cim/cim_df.c
new file mode 100644
index 0000000..805b28f
--- /dev/null
+++ b/lib/cimarron/cim/cim_df.c
@@ -0,0 +1,2544 @@
+ /*
+  * <LIC_AMD_STD>
+  * Copyright (C) 2005 Advanced Micro Devices, Inc.  All Rights Reserved.
+  * </LIC_AMD_STD>
+  *
+  * <CTL_AMD_STD>
+  * </CTL_AMD_STD>
+  *
+  * <DOC_AMD_STD>
+  * Cimarron display filter routines.  These routines program the video hardware.
+  * </DOC_AMD_STD>
+  *
+  */
+
+/*---------------------------------------------------------------------------
+ * df_set_crt_enable
+ *
+ * This routine enables or disables CRT output.
+ *---------------------------------------------------------------------------*/
+
+int df_set_crt_enable (int crt_output)
+{
+	unsigned long config, misc;
+	
+	config = READ_VID32 (DF_DISPLAY_CONFIG);
+	misc   = READ_VID32 (DF_VID_MISC);
+	
+	switch (crt_output)
+	{
+		/* DISABLE DISPLAY */
+
+	    case DF_CRT_DISABLE:
+
+			config &= ~(DF_DCFG_DIS_EN   | DF_DCFG_HSYNC_EN |
+				        DF_DCFG_VSYNC_EN | DF_DCFG_DAC_BL_EN);
+			misc |= DF_DAC_POWER_DOWN;
+			break;
+
+		/* ENABLE THE DISPLAY */
+
+		case DF_CRT_ENABLE:
+
+			config |= (DF_DCFG_DIS_EN   | DF_DCFG_HSYNC_EN |
+				       DF_DCFG_VSYNC_EN | DF_DCFG_DAC_BL_EN);
+			misc &= ~(DF_DAC_POWER_DOWN  | DF_ANALOG_POWER_DOWN);
+			break;
+
+		/* HSYNC:OFF VSYNC:ON */
+
+		case DF_CRT_STANDBY:
+
+			config = (config & ~(DF_DCFG_DIS_EN | DF_DCFG_HSYNC_EN | DF_DCFG_DAC_BL_EN)) |
+				DF_DCFG_VSYNC_EN;
+			misc |= DF_DAC_POWER_DOWN;
+			break;
+
+		/* HSYNC:ON VSYNC:OFF */
+
+		case DF_CRT_SUSPEND:
+
+			config = (config & ~(DF_DCFG_DIS_EN | DF_DCFG_VSYNC_EN | DF_DCFG_DAC_BL_EN)) |
+				DF_DCFG_HSYNC_EN;
+			misc |= DF_DAC_POWER_DOWN;
+			break;
+
+		default:
+			return CIM_STATUS_INVALIDPARAMS;
+	}
+
+	WRITE_VID32 (DF_DISPLAY_CONFIG, config);
+	WRITE_VID32 (DF_VID_MISC, misc);
+
+	return CIM_STATUS_OK;
+}
+
+/*---------------------------------------------------------------------------
+ * df_set_panel_enable
+ *
+ * This routine enables or disables panel output.
+ *---------------------------------------------------------------------------*/
+
+int df_set_panel_enable (int enable)
+{
+	unsigned long pm;
+	
+	pm = READ_VID32 (DF_POWER_MANAGEMENT);
+
+	if (enable) pm |=  DF_PM_PANEL_ON;
+	else        pm &= ~DF_PM_PANEL_ON;
+
+	WRITE_VID32 (DF_POWER_MANAGEMENT, pm);
+	
+	return CIM_STATUS_OK;
+}
+
+/*---------------------------------------------------------------------------
+ * df_configure_video_source
+ *
+ * This routine initializes all aspects of the source buffer for a video overlay.
+ *---------------------------------------------------------------------------*/
+
+int df_configure_video_source (DF_VIDEO_SOURCE_PARAMS *video_source_odd,
+	DF_VIDEO_SOURCE_PARAMS *video_source_even)
+{
+	unsigned long pitch, ctrl, vcfg;
+	unsigned long lock, vg_line, gcfg;
+	unsigned long width, size, scale;
+    unsigned long misc;
+
+	lock    = READ_REG32 (DC3_UNLOCK);
+	vg_line = READ_REG32 (DC3_LINE_SIZE);
+	gcfg    = READ_REG32 (DC3_GENERAL_CFG);
+	vcfg    = READ_VID32 (DF_VIDEO_CONFIG);
+	ctrl    = READ_VID32 (DF_VID_ALPHA_CONTROL);
+	scale   = READ_VID32 (DF_VIDEO_SCALER);
+
+    /* STORE THE DESIRED SCALING PROCEDURE */
+    /* Cimarron supports two modes when programming the scale and position  */
+    /* of the video window.  The first mode is designed to implicitly apply */
+    /* the graphics scale to any video operations.  The second applys the   */
+    /* video unchanged, allowing complete control by the user.  To allow    */
+    /* visibility between modules, the current mode is stored in a spare    */
+    /* bit in the DF miscellaneous register.                                */
+
+    misc = READ_VID32 (DF_VID_MISC);
+    if (video_source_odd->flags & DF_SOURCEFLAG_IMPLICITSCALING)
+        misc |= DF_USER_IMPLICIT_SCALING;
+    else
+        misc &= DF_USER_IMPLICIT_SCALING;
+    WRITE_VID32 (DF_VID_MISC, misc);
+
+	/* PARAMETER - VIDEO PITCH */
+
+	pitch = (video_source_odd->y_pitch >> 3) | ((video_source_odd->uv_pitch >> 3) << 16);
+	
+	/* PARAMETER - VIDEO FORMAT */
+
+	gcfg &= ~DC3_GCFG_YUV_420;
+	vcfg &= ~(DF_VCFG_VID_INP_FORMAT | DF_VCFG_4_2_0_MODE);
+	ctrl &= ~(DF_VIDEO_INPUT_IS_RGB  | DF_CSC_VIDEO_YUV_TO_RGB | DF_HD_VIDEO |
+		DF_YUV_CSC_EN);
+		
+	/* SELECT PIXEL ORDERING */
+
+	switch (video_source_odd->video_format & 3)
+	{
+		case 0: vcfg |= DF_VCFG_UYVY_FORMAT; break;
+		case 1: vcfg |= DF_VCFG_Y2YU_FORMAT; break;
+		case 2: vcfg |= DF_VCFG_YUYV_FORMAT; break;
+		case 3: vcfg |= DF_VCFG_YVYU_FORMAT; break;
+	}
+
+	/* SELECT SOURCE FORMAT (4:2:2, 4:2:0, RGB) */
+
+	switch (video_source_odd->video_format >> 2)
+	{
+		case 0:  ctrl |= DF_CSC_VIDEO_YUV_TO_RGB; break;
+		
+		case 1:  ctrl |= DF_CSC_VIDEO_YUV_TO_RGB;
+			     vcfg |= DF_VCFG_4_2_0_MODE;
+				 gcfg |= DC3_GCFG_YUV_420;
+				 break;
+		
+		case 2:  ctrl |= DF_VIDEO_INPUT_IS_RGB; break;
+		
+		default: return CIM_STATUS_INVALIDPARAMS;
+	}
+
+	/* ALIGN TO APPROPRIATE OUTPUT COLOR SPACE                             */
+	/* We have assumed until this point that the output color space is RGB */
+	/* and the input (if YUV) is always SDTV video.                        */
+
+	if (video_source_odd->flags & DF_SOURCEFLAG_HDTVSOURCE)
+		ctrl |= DF_HD_VIDEO;
+
+	if (ctrl & DF_CSC_GRAPHICS_RGB_TO_YUV)
+	{
+		/* YUV OUTPUT - DISABLE YUV->RGB AND ENABLE YUV->YUV */
+
+		ctrl &= ~DF_CSC_VIDEO_YUV_TO_RGB;
+
+		if ((!(ctrl & DF_HD_VIDEO) &&  (ctrl & DF_HD_GRAPHICS)) ||
+			 ((ctrl & DF_HD_VIDEO) && !(ctrl & DF_HD_GRAPHICS)))
+		{
+			ctrl |= DF_YUV_CSC_EN;
+		}
+	}
+
+	/* PARAMETER - DISPLAY FILTER BUFFER SIZE                        */
+	/* The line size in the video generator must be 32-byte aligned. */
+	/* However, smaller alignments are managed by setting the        */
+	/* appropriate pitch and clipping the video window.              */
+	
+	vcfg &= ~(DF_VCFG_LINE_SIZE_LOWER_MASK | DF_VCFG_LINE_SIZE_BIT8 |
+		      DF_VCFG_LINE_SIZE_BIT9);
+
+	size  = ((video_source_odd->width >> 1) + 7) & 0xFFF8;
+
+	vcfg |= (size & 0x00FF) << 8;
+	if (size & 0x0100) vcfg |= DF_VCFG_LINE_SIZE_BIT8;
+	if (size & 0x0200) vcfg |= DF_VCFG_LINE_SIZE_BIT9;
+
+	scale = (scale & ~0x7FF) | video_source_odd->height;
+
+	/* PARAMETER - VIDEO GENERATOR BUFFER SIZE */
+	
+	vg_line &= ~DC3_LINE_SIZE_VLS_MASK;
+
+	if (gcfg & DC3_GCFG_YUV_420)
+		width = ((video_source_odd->width >> 1) + 7) & 0xFFF8;
+	else
+		width = ((video_source_odd->width << 1) + 31) & 0xFFE0;
+
+	vg_line |= (width >> 3) << DC3_LINE_SIZE_VB_SHIFT;
+
+	/* WRITE ALL PARAMETERS AT ONCE */
+	
+	WRITE_REG32 (DC3_UNLOCK, DC3_UNLOCK_VALUE);
+	WRITE_VID32 (DF_VIDEO_CONFIG, vcfg);
+	WRITE_VID32 (DF_VID_ALPHA_CONTROL, ctrl);
+	WRITE_VID32 (DF_VIDEO_SCALER, scale);
+	WRITE_REG32 (DC3_GENERAL_CFG, gcfg);
+	WRITE_REG32 (DC3_LINE_SIZE, vg_line);
+	WRITE_REG32 (DC3_VID_YUV_PITCH, pitch);
+
+	/* WRITE EVEN OR ODD BUFFER OFFSETS                            */
+	/* The even buffer is only valid inside an interlaced display. */
+	
+    if (READ_REG32 (DC3_IRQ_FILT_CTL) & DC3_IRQFILT_INTL_EN)
+	{
+		WRITE_REG32 (DC3_VID_EVEN_Y_ST_OFFSET, video_source_even->y_offset);
+		WRITE_REG32 (DC3_VID_EVEN_U_ST_OFFSET, video_source_even->u_offset);
+		WRITE_REG32 (DC3_VID_EVEN_V_ST_OFFSET, video_source_even->v_offset);
+	}
+
+	WRITE_REG32 (DC3_VID_Y_ST_OFFSET, video_source_odd->y_offset);
+	WRITE_REG32 (DC3_VID_U_ST_OFFSET, video_source_odd->u_offset);
+	WRITE_REG32 (DC3_VID_V_ST_OFFSET, video_source_odd->v_offset);
+
+    WRITE_REG32 (DC3_UNLOCK, lock);
+
+	return CIM_STATUS_OK;
+}
+
+/*---------------------------------------------------------------------------
+ * df_set_video_offsets
+ *
+ * This routine sets the starting offset for the video buffer(s).  The buffers
+ * can also be configured inside df_configure_video_source, but a separate
+ * routine is provided here to allow quick buffer flipping.
+ *---------------------------------------------------------------------------*/
+
+int df_set_video_offsets (int even, unsigned long y_offset,
+	unsigned long u_offset, unsigned long v_offset)
+{
+	unsigned long lock = READ_REG32 (DC3_UNLOCK);
+
+	WRITE_REG32 (DC3_UNLOCK, DC3_UNLOCK_VALUE);
+	
+    if (even)
+	{		
+		WRITE_REG32 (DC3_VID_EVEN_Y_ST_OFFSET, y_offset);
+		WRITE_REG32 (DC3_VID_EVEN_U_ST_OFFSET, u_offset);
+		WRITE_REG32 (DC3_VID_EVEN_V_ST_OFFSET, v_offset);
+	}
+	else
+	{
+		WRITE_REG32 (DC3_VID_Y_ST_OFFSET, y_offset);
+		WRITE_REG32 (DC3_VID_U_ST_OFFSET, u_offset);
+		WRITE_REG32 (DC3_VID_V_ST_OFFSET, v_offset);
+	}
+
+	WRITE_REG32 (DC3_UNLOCK, lock);
+
+	return CIM_STATUS_OK;
+}
+
+/*---------------------------------------------------------------------------
+ * df_set_video_scale
+ *
+ * This routine programs the horizontal/vertical scale factors for video.  To
+ * disable scaling/filtering, this routine should be called with identical source
+ * and destination dimensions.
+ *---------------------------------------------------------------------------*/
+
+int df_set_video_scale (unsigned long src_width, unsigned long src_height,
+	unsigned long dst_width, unsigned long dst_height, unsigned long flags)
+{
+	unsigned long temp, misc;
+    unsigned long scale, gfxscale;
+    unsigned long fbactive, src;
+    unsigned long size, downscale;
+    unsigned long vcfg, gcfg, unlock;
+
+    /* APPLY THE GRAPHICS SCALE */
+    /* When requested by the user, we will adjust the video scale by the  */
+    /* current graphics scale factor.  This allows video to be programmed */
+    /* in terms of the graphics source resolution.                        */
+
+    misc = READ_VID32 (DF_VID_MISC);
+    if (misc & DF_USER_IMPLICIT_SCALING)
+    {
+        gfxscale = READ_REG32 (DC3_GFX_SCALE);
+        fbactive = READ_REG32 (DC3_FB_ACTIVE);
+
+        /* REVERSE ENGINEER THE SCALE FACTOR */
+        /* The graphics scale factor is (source / (dst - 1)), so a little */
+        /* math is performed to reverse engineer the correct scale for    */
+        /* video.                                                         */
+        /*                                                                */
+        /* F = (0x4000*S)/(D-1)  ->  (D/S) = (((0x4000*S)/F)+1)/S         */
+
+        scale =  gfxscale & 0xFFFF;
+        src   = (fbactive >> 16) + 1;
+        if (scale != 0x4000)
+        {
+            dst_width = dst_width * (((0x4000 * src) / scale) + 1);
+            dst_width /= src;
+        }
+
+        scale =  gfxscale >> 16;
+        src   = (fbactive & 0xFFFF) + 1;
+        if (scale != 0x4000)
+        {
+            dst_height = dst_height * (((0x4000 * src) / scale) + 1);
+            dst_height /= src;
+        }
+    }
+
+	/* CHECK FOR VALID SCALING FACTOR */
+	/* The display filter/video generator can support up to 8:1  */
+    /* horizontal downscale and up to 4:1 vertical downscale.    */
+    /* Scale factors above 4:1 horizontal and 2:1 horizontal     */
+    /* will have a quality impact.  However, at such large scale */
+    /* factors, it might not matter,                             */
+
+	if (((flags & DF_SCALEFLAG_CHANGEX) && dst_width  < (src_width >> 3)) ||
+        ((flags & DF_SCALEFLAG_CHANGEY) && dst_height < (src_height >> 2)))
+    {
+		return CIM_STATUS_INVALIDSCALE;
+    }
+
+    /* ENABLE OR DISABLE ADVANCED SCALING FEATURES          */
+    /* Scaling above 2:1 vertical and 4:1 horizontal relies */
+    /* on mechanisms beside the line filter.                */
+    
+    if (flags & DF_SCALEFLAG_CHANGEX)
+    {
+        scale = READ_VID32 (DF_VIDEO_SCALER);
+        vcfg  = READ_VID32 (DF_VIDEO_CONFIG);
+        vcfg &= ~(DF_VCFG_LINE_SIZE_LOWER_MASK | DF_VCFG_LINE_SIZE_BIT8 |
+		      DF_VCFG_LINE_SIZE_BIT9);
+        
+        if (dst_width < (src_width >> 2))
+        {            
+            src_width >>= 1;
+            WRITE_VID32 (DF_VIDEO_SCALER, scale | DF_SCALE_DOUBLE_H_DOWNSCALE);
+        }
+        else
+        {
+            WRITE_VID32 (DF_VIDEO_SCALER, scale & ~DF_SCALE_DOUBLE_H_DOWNSCALE);
+        }
+        
+        /* PROGRAM A NEW LINE SIZE */
+        /* The line size must be updated when using the Double Horizontal  */
+        /* Downscale (DHD) bit.  This is because the amount of VFIFO space */
+        /* consumed is effectively half in this mode.                      */
+
+        size  = ((src_width >> 1) + 7) & 0xFFF8;
+	    vcfg |= (size & 0x00FF) << 8;
+	    if (size & 0x0100) vcfg |= DF_VCFG_LINE_SIZE_BIT8;
+	    if (size & 0x0200) vcfg |= DF_VCFG_LINE_SIZE_BIT9;
+        WRITE_VID32 (DF_VIDEO_CONFIG, vcfg);
+        WRITE_VID32 (DF_VIDEO_XSCALE, ((0x10000 * src_width) / dst_width));
+    }
+    if (flags & DF_SCALEFLAG_CHANGEY)
+    {
+        unlock = READ_REG32 (DC3_UNLOCK);
+        gcfg   = READ_REG32 (DC3_GENERAL_CFG) & ~DC3_GCFG_VDSE;
+        WRITE_REG32 (DC3_UNLOCK, DC3_UNLOCK_VALUE);
+        if (dst_height < (src_height >> 1))
+        {
+            gcfg |= DC3_GCFG_VDSE;
+            downscale = READ_REG32 (DC3_VID_DS_DELTA) & ~DC3_DS_DELTA_MASK;
+            if (dst_height == (src_height >> 2))
+                downscale |= (0x3FFF << 18);
+            else
+                downscale |= (((src_height >> 1) << 14) / dst_height) << 18;
+            
+            WRITE_REG32 (DC3_VID_DS_DELTA, downscale);
+            WRITE_VID32 (DF_VIDEO_YSCALE, 0x20000);
+        }
+        else
+        {
+            WRITE_VID32 (DF_VIDEO_YSCALE, ((0x10000 * src_height) / dst_height));
+        }
+        WRITE_REG32 (DC3_GENERAL_CFG, gcfg);
+        WRITE_REG32 (DC3_UNLOCK, unlock);
+    }
+
+	/* CHECK IF SCALING IS DISABLED */
+	/* If no scaling occurs, we disable the hardware filter. */
+
+	temp = READ_VID32 (DF_VIDEO_CONFIG);
+	if ((READ_VID32 (DF_VIDEO_XSCALE) == 0x10000) &&
+		(READ_VID32 (DF_VIDEO_YSCALE) == 0x10000))
+	{
+		WRITE_VID32 (DF_VIDEO_CONFIG, (temp | DF_VCFG_SC_BYP));
+	}
+	else
+		WRITE_VID32 (DF_VIDEO_CONFIG, (temp & ~DF_VCFG_SC_BYP));
+
+	return CIM_STATUS_OK;
+}
+
+/*---------------------------------------------------------------------------
+ * df_set_video_position
+ *
+ * This routine programs the position of the video window on the display.
+ * An indent parameter is also passed to this program to prevent artifacts
+ * when the video window is moved beyond the left edge of the screen.
+ *---------------------------------------------------------------------------*/
+
+int df_set_video_position (DF_VIDEO_POSITION *video_window)
+{
+	unsigned long vblankstart_even, vblankend_even, vsyncend_even, vtotal_even, vactive_even;
+    unsigned long hblankstart, hblankend, hsyncend, htotal, hactive;
+	unsigned long vblankstart, vblankend, vsyncend, vtotal, vactive;
+    unsigned long width, height, height_even;
+    unsigned long adjust, border_x, border_y, border_y_even;
+	unsigned long xstart, xend;
+	unsigned long ystart, yend;
+	unsigned long ckey_x, ckey_y;
+    unsigned long x_copy, y_copy;
+    unsigned long width_copy, height_copy;
+	unsigned long vcfg, initread;
+    unsigned long xscale, dst_clip;
+    unsigned long ypos, ypos_even;
+    unsigned long y, gfxscale;
+    unsigned long misc, fbactive;
+    unsigned long scale, src;
+    unsigned long irq_ctl;
+    unsigned long unlock;
+
+	hsyncend    = ((READ_REG32 (DC3_H_SYNC_TIMING)   >> 16) & 0xFFF) + 1;
+	vsyncend    = ((READ_REG32 (DC3_V_SYNC_TIMING)   >> 16) & 0xFFF) + 1;
+    vblankend   = ((READ_REG32 (DC3_V_BLANK_TIMING)   >> 16) & 0xFFF) + 1;
+    hblankend   = ((READ_REG32 (DC3_H_BLANK_TIMING)   >> 16) & 0xFFF) + 1;
+	htotal      = ((READ_REG32 (DC3_H_ACTIVE_TIMING) >> 16) & 0xFFF) + 1;
+	vtotal      = ((READ_REG32 (DC3_V_ACTIVE_TIMING) >> 16) & 0xFFF) + 1;
+	vblankstart =  (READ_REG32 (DC3_V_BLANK_TIMING)  & 0xFFF) + 1;
+    hblankstart =  (READ_REG32 (DC3_H_BLANK_TIMING)  & 0xFFF) + 1;
+    hactive     =  (READ_REG32 (DC3_H_ACTIVE_TIMING) & 0xFFF) + 1;
+	vactive     =  (READ_REG32 (DC3_V_ACTIVE_TIMING) & 0xFFF) + 1;
+    unlock      =   READ_REG32 (DC3_UNLOCK);
+
+    /* INCLUDE BORDER IF REQUESTED */
+
+    if (video_window->flags & DF_POSFLAG_INCLUDEBORDER)
+    {
+        border_x = htotal - hblankend;
+        border_y = vtotal - vblankend;
+        hactive = hblankstart + htotal - hblankend;
+        vactive = vblankstart + vtotal - vblankend;
+    }
+    else
+    {
+        border_x = border_y = 0;
+    }
+
+    /* APPLY THE GRAPHICS SCALE     */
+    /* Do not alter the input data. */
+
+    width_copy  = video_window->width;
+    height_copy = video_window->height;
+    x_copy = video_window->x;
+    y_copy = video_window->y;
+
+    misc = READ_VID32 (DF_VID_MISC);
+    if (misc & DF_USER_IMPLICIT_SCALING)
+    {
+        gfxscale = READ_REG32 (DC3_GFX_SCALE);
+        fbactive = READ_REG32 (DC3_FB_ACTIVE);
+
+        /* REVERSE ENGINEER THE SCALE FACTOR */
+
+        scale =  gfxscale & 0xFFFF;
+        src   = (fbactive >> 16) + 1;
+        if (scale != 0x4000)
+        {
+            width_copy = width_copy * (((0x4000 * src) / scale) + 1);
+            width_copy /= src;
+            x_copy = x_copy * (((0x4000 * src) / scale) + 1);
+            x_copy /= src;
+        }
+
+        scale =  gfxscale >> 16;
+        src   = (fbactive & 0xFFFF) + 1;
+        if (scale != 0x4000)
+        {
+            height_copy = height_copy * (((0x4000 * src) / scale) + 1);
+            height_copy /= src;
+            y_copy = y_copy * (((0x4000 * src) / scale) + 1);
+            y_copy /= src;
+        }
+    }
+
+    /* HANDLE INTERLACING */
+    /* When the output is interlaced, we must set the position and height */
+    /* on the fields and not on the composite image.                      */
+
+    if ((irq_ctl = READ_REG32 (DC3_IRQ_FILT_CTL)) & DC3_IRQFILT_INTL_EN)
+    {
+        vsyncend_even    = ((READ_REG32 (DC3_V_SYNC_EVEN)   >> 16) & 0xFFF) + 1;
+        vtotal_even      = ((READ_REG32 (DC3_V_ACTIVE_EVEN) >> 16) & 0xFFF) + 1;
+        vblankend_even   = ((READ_REG32 (DC3_V_BLANK_EVEN)  >> 16) & 0xFFF) + 1;
+        vactive_even     =  (READ_REG32 (DC3_V_ACTIVE_EVEN) & 0xFFF) + 1;
+        vblankstart_even =  (READ_REG32 (DC3_V_BLANK_EVEN)  & 0xFFF) + 1;
+
+        if (video_window->flags & DF_POSFLAG_INCLUDEBORDER)
+        {
+            border_y_even = vtotal_even- vblankend_even;
+            vactive_even = vblankstart_even + vtotal_even - vblankend_even;
+        }
+        else
+            border_y_even = 0;
+
+        /* THE ODD FIELD MUST ALWAYS PRECEDE THE EVEN FIELD */
+        /* This implies that we can never start video on an odd y position   */
+        /* in the composite image.  This is required because the only way to */
+        /* accomplish an odd y start would be to switch the buffer offsets,  */
+        /* which could have serious repercussions for genlocked VIP.         */
+
+        y = y_copy >> 1;
+
+        /* CALCULATE Y POSITION FOR ODD FIELD */
+        /* Clip the video window to the odd field timings. Note that the */
+        /* height in the odd field may be greater if the video height is */
+        /* odd.                                                          */
+
+        height = (height_copy + 1) >> 1;
+        if ((y + height) > vactive)
+		    height = vactive - y;
+
+        ystart = y + vtotal_even - vsyncend_even + 1;
+        if (video_window->flags & DF_POSFLAG_INCLUDEBORDER)
+            ystart -= border_y_even;
+
+        yend   = ystart + height;
+        ypos   = (yend << 16) | ystart;
+
+        /* CALCULATE Y POSITION FOR EVEN FIELD */
+
+        height_even = height_copy >> 1;
+        if ((y + height_even) > vactive_even)
+		    height_even = vactive_even - y;
+
+        ystart = y + vtotal - vsyncend + 1;
+        if (video_window->flags & DF_POSFLAG_INCLUDEBORDER)
+            ystart -= border_y;
+
+        yend = ystart + height_even;
+        ypos_even = (yend << 16) | ystart;
+
+        /* CALCULATE ACTUAL FRAME BUFFER HEIGHT */
+        /* The y position and height are used to determine the actual    */
+        /* placement of the color key region.  The region will either be */
+        /* the sum of the even and odd fields (for interlaced addressing */
+        /* or flicker filtering) or it will be the union of the two (for */
+        /* line doubling).  We must also adjust the region such that the */
+        /* origin (0, 0) is centered on the beginning of graphics data.  */
+        /* This is only a problem if video is being displayed over the   */
+        /* overscan area.                                                */
+
+        if ((READ_REG32 (DC3_GENLK_CTL) & DC3_GC_FLICKER_FILTER_ENABLE) ||
+            (irq_ctl & DC3_IRQFILT_INTL_ADDR))
+        {
+            y <<= 1;
+            height += height_even;
+            adjust = border_y + border_y_even;
+        }
+        else
+        {
+            adjust = border_y;
+            if (height_even > height)
+                height = height_even;
+        }
+        if (video_window->flags & DF_POSFLAG_INCLUDEBORDER)
+        {
+            if (y > adjust)
+            {
+                y -= adjust;
+                adjust = 0;
+            }
+            else
+            {
+                adjust -= y;
+                if (height > adjust)
+                    height -= adjust;
+                else
+                    height = 0;
+            }
+        }
+
+    }
+    else
+    {
+        y = y_copy;
+
+        height = height_copy;
+        if ((y + height) > vactive)
+		    height = vactive - y;
+
+        ystart = y + vtotal - vsyncend + 1;
+        if (video_window->flags & DF_POSFLAG_INCLUDEBORDER)
+            ystart -= border_y;
+
+        yend = ystart + height;
+        ypos = (yend << 16) | ystart;
+        ypos_even = 0;
+    }
+	
+    /* HORIZONTAL POSITION */
+    /* The horizontal values are identical for the even and odd field. */
+
+    width   = width_copy;
+	xstart  = x_copy + htotal - hsyncend - 14;
+    if (video_window->flags & DF_POSFLAG_INCLUDEBORDER)
+        xstart -= border_x;
+
+	/* RIGHT CLIPPING */
+
+	if ((x_copy + width) > hactive)
+		width = hactive - x_copy;
+	
+	xend = xstart + width;
+	
+	/* CALCULATE LEFT CLIPPING PARAMETER */
+	/* The value passed in can be interpreted as destination pixels, in which   */
+	/* case the video scale is factored in, or as source pixels, in which case  */
+	/* the value is written directly.  Also, the display filter's initial read  */
+	/* address value is only programmable on 4-pixel increments.  However, we   */
+	/* can achieve an arbitrary left clip by adjusting the xstart value, as     */
+	/* there is a 14-clock delay in which to play.  Also, according to the      */
+	/* designers, 4:2:0 and 4:2:2 behave identically when setting the initial   */
+	/* read address.  The addition of scaling further complicates the           */
+    /* algorithm.  When setting the initial read address, it is in terms of     */
+    /* source pixels, while adjusting the xstart value is in destination pixels */
+    /* We may thus not be able to achieve a perfect clipping fit for scaled     */
+    /* video.   We compensate by including two clipping parameters in our       */
+    /* structure.  This allows us the user additional control and it allows us  */
+    /* to accurately convey to the user the state of clipping on the machine.   */
+
+	initread = video_window->left_clip;
+    dst_clip = 0;
+	if (!(video_window->flags & DF_POSFLAG_DIRECTCLIP))
+    {
+        xscale = READ_VID32 (DF_VIDEO_XSCALE) & 0xFFFFF;
+		initread =  (initread * xscale) / 0x10000;
+        if (xscale)
+            dst_clip = ((initread & 3) * 0x10000) / xscale;
+    }
+    else
+        dst_clip = video_window->dst_clip;
+		
+    /* LIMIT THE CLIP */
+    /* We technically have a 14 pixel window in which to play.  However, taking */
+    /* the entire 14 pixels makes the video timing a little hairy...  Also note */
+    /* that we cannot do this when performing panel centering, as the video     */
+    /* would then exceed the mode size.                                         */
+
+    if (dst_clip > 4)
+        dst_clip = 4;
+    if (READ_REG32 (DC3_DISPLAY_CFG) & DC3_DCFG_DCEN)
+        dst_clip = 0;
+
+	xstart -= dst_clip;
+    	
+	vcfg = READ_VID32 (DF_VIDEO_CONFIG);
+	vcfg &= ~DF_VCFG_INIT_READ_MASK;
+	vcfg |= (initread >> 2) << 16;
+
+	/* SET COLOR KEY REGION */
+	/* We are assuming that color keying will never be desired outside   */
+	/* of the video region.  We adjust the color key region for graphics */
+    /* scaling.                                                          */
+
+    gfxscale = READ_REG32 (DC3_GFX_SCALE);
+
+    ckey_x =   ((x_copy * (gfxscale & 0xFFFF)) / 0x4000) |
+             ((((x_copy + width) * (gfxscale & 0xFFFF)) / 0x4000) << 16);
+	ckey_y =   ((y * (gfxscale >> 16)) / 0x4000) |
+             ((((y + height) * (gfxscale >> 16)) / 0x4000) << 16);
+
+	/* WRITE ALL PARAMETERS AT ONCE */
+
+    WRITE_REG32 (DC3_UNLOCK, DC3_UNLOCK_VALUE);
+	WRITE_REG32 (DC3_CLR_KEY_X, ckey_x);
+	WRITE_REG32 (DC3_CLR_KEY_Y, ckey_y);
+	WRITE_VID32 (DF_VIDEO_X_POS, (xend << 16) | xstart);
+	WRITE_VID32 (DF_VIDEO_Y_POS, ypos);
+    WRITE_VID32 (DF_VID_YPOS_EVEN, ypos_even);
+	WRITE_VID32 (DF_VIDEO_CONFIG, vcfg);
+    WRITE_REG32 (DC3_UNLOCK, unlock);
+
+	return CIM_STATUS_OK;
+}
+
+/*---------------------------------------------------------------------------
+ * df_set_video_filter_coefficients
+ *
+ * This routine sets the horizontal and vertical filter coefficients for video
+ * scaling.  These coefficients are used for upscaling and downscaling video.
+ * If the phase256 parameter is 1, the coefficient arrays are used as single
+ * arrays of 256 phases for both vertical and horizontal scaling.  If the
+ * phase256 parameter is clear, the coefficient arrays are used as two 128-phase
+ * arrays.  The first 128 entries represent the phases for vertical scaling.
+ * The last 128 entries represent the phases for horizontal scaling.
+ *---------------------------------------------------------------------------*/
+
+int df_set_video_filter_coefficients (long taps[][4], int phase256)
+{
+	unsigned long scale, coeff0, coeff1;
+	unsigned long i;
+	long (*defaults)[2];
+
+	/* SET PHASE COUNT AND CHOOSE COEFFICIENT ARRAY */
+
+	scale = READ_VID32 (DF_VIDEO_SCALER);
+	if (phase256)
+	{
+		WRITE_VID32 (DF_VIDEO_SCALER, (scale & ~DF_SCALE_128_PHASES));
+		defaults = CimarronVideoFilter256;	
+	}
+	else
+	{
+		WRITE_VID32 (DF_VIDEO_SCALER, (scale | DF_SCALE_128_PHASES));
+		defaults = CimarronVideoFilter128;		
+	}
+
+	/* PROGRAM COEFFICIENTS */
+
+	for (i = 0; i < 256; i++)
+	{
+        if (!taps)
+        {
+            coeff0 = defaults[i][0];
+            coeff1 = defaults[i][1];
+        }
+        else
+        {
+		    if (taps[i][1] < 0)  coeff0 = -taps[i][1] | 0x8000;
+		    else                 coeff0 =  taps[i][1];
+
+		    coeff0 <<= 16;
+
+		    if (taps[i][0] < 0)  coeff0 |= -taps[i][0] | 0x8000;
+		    else                 coeff0 |=  taps[i][0];
+
+		
+
+		    if (taps[i][3] < 0)  coeff1 = -taps[i][3] | 0x8000;
+		    else                 coeff1 =  taps[i][3];
+
+		    coeff1 <<= 16;
+
+		    if (taps[i][2] < 0)  coeff1 |= -taps[i][2] | 0x8000;
+		    else                 coeff1 |=  taps[i][2];
+        }
+
+        WRITE_VID32 ((DF_COEFFICIENT_BASE + (i << 3)), coeff0);
+		WRITE_VID32 ((DF_COEFFICIENT_BASE + (i << 3) + 4), coeff1);
+	}
+
+	return CIM_STATUS_OK;
+}
+
+/*---------------------------------------------------------------------------
+ * df_set_video_enable
+ *
+ * This routine enables or disables the video overlay.
+ *---------------------------------------------------------------------------*/
+
+int df_set_video_enable (int enable, unsigned long flags)
+{
+	unsigned long vcfg, lock, gcfg;
+    unsigned long dcfg, vg_ckey, fifo = 0;
+
+	vcfg = READ_VID32 (DF_VIDEO_CONFIG);
+	lock = READ_REG32 (DC3_UNLOCK);
+    gcfg = READ_REG32 (DC3_GENERAL_CFG);
+
+    /* SET VIDEO FIFO END WATERMARK */
+    /* The video FIFO end watermark is set to 0 when video is disabled  */
+    /* to allow low priority transactions in the VG.  Otherwise, the    */
+    /* priority will be forced high until the VG fills the video FIFO   */
+    /* by not fetching video.  That could take a while...  Note that    */
+    /* we set the end priority to be 4 greater than the start.  We      */
+    /* assume that the start priority has been configured by a modeset. */
+
+    dcfg = READ_REG32 (DC3_DISPLAY_CFG) & ~DC3_DCFG_VFHPEL_MASK;
+    if (enable)
+    {
+        fifo = ((dcfg >> 12) & 0x0000000F) + 4;
+        if (fifo > 0xF)
+            fifo = 0xF;
+    }
+    WRITE_REG32 (DC3_UNLOCK, DC3_UNLOCK_VALUE);
+    WRITE_REG32 (DC3_DISPLAY_CFG, dcfg | (fifo << 16));
+
+	/* ENABLE OR DISABLE VIDEO */
+	/* The mechanism to fetch video data is enabled first and */
+	/* disabled last.                                         */
+
+	if (enable)
+	{
+        WRITE_REG32 (DC3_GENERAL_CFG, (gcfg | DC3_GCFG_VIDE));
+		WRITE_VID32 (DF_VIDEO_CONFIG, (vcfg | DF_VCFG_VID_EN));
+
+        /* DISABLE COLOR KEYING IF REQUESTED BY THE USER */
+
+        if (flags & DF_ENABLEFLAG_NOCOLORKEY)
+        {
+            /* OVERRIDE THE MODE TO COLOR KEYING */
+
+            dcfg = READ_VID32 (DF_DISPLAY_CONFIG);
+            WRITE_VID32 (DF_DISPLAY_CONFIG, (dcfg & ~DF_DCFG_VG_CK));
+
+            /* DISABLE COLOR KEYING IN THE VG */
+
+            vg_ckey = READ_REG32 (DC3_COLOR_KEY);
+            WRITE_REG32 (DC3_COLOR_KEY, (vg_ckey & ~DC3_CLR_KEY_ENABLE));
+        }
+        else if (!(READ_VID32 (DF_DISPLAY_CONFIG) & DF_DCFG_VG_CK))
+        {
+            /* OTHERWISE RE-ENABLE COLOR KEYING */
+
+            vg_ckey = READ_REG32 (DC3_COLOR_KEY);
+            WRITE_REG32 (DC3_COLOR_KEY, (vg_ckey | DC3_CLR_KEY_ENABLE));
+        }
+	}
+	else
+	{
+		WRITE_VID32 (DF_VIDEO_CONFIG, (vcfg & ~DF_VCFG_VID_EN));
+        WRITE_REG32 (DC3_GENERAL_CFG, (gcfg & ~DC3_GCFG_VIDE));
+
+        /* DISABLE COLOR KEY WINDOW WHEN VIDEO IS INACTIVE         */
+        /* To mimic legacy functionality, we disble color keying   */
+        /* when the video window is not active.  We will restore   */
+        /* the enable when video is re-enabled if the appropriate  */
+        /* bit is set in display config.                           */
+
+        vg_ckey = READ_REG32 (DC3_COLOR_KEY);
+        WRITE_REG32 (DC3_COLOR_KEY, (vg_ckey & ~DC3_CLR_KEY_ENABLE));
+	}
+	WRITE_REG32 (DC3_UNLOCK, lock);
+
+	return CIM_STATUS_OK;
+}
+
+/*---------------------------------------------------------------------------
+ * df_set_video_color_key
+ *
+ * This routine configures the video color/chroma key mechanism.
+ *---------------------------------------------------------------------------*/
+
+int df_set_video_color_key (unsigned long key, unsigned long mask, int graphics)
+{
+	unsigned long lock, vg_ckey, df_dcfg;
+
+	vg_ckey = READ_REG32 (DC3_COLOR_KEY);
+    lock    = READ_REG32 (DC3_UNLOCK);
+	df_dcfg = READ_VID32 (DF_DISPLAY_CONFIG);
+	
+    WRITE_REG32 (DC3_UNLOCK, DC3_UNLOCK_VALUE);
+
+	if (graphics)
+	{
+        /* COLOR KEY - USE VG HARDWARE */
+        /* Note that color key is never enabled unless a video window */
+        /* is active.  This is to match legacy behavior.              */
+
+		df_dcfg &= ~DF_DCFG_VG_CK;
+        vg_ckey = (vg_ckey & 0xFF000000) | (key & 0xFFFFFF);
+        if (READ_VID32 (DF_VIDEO_CONFIG) & DF_VCFG_VID_EN)
+            vg_ckey |=  DC3_CLR_KEY_ENABLE;
+        else
+            vg_ckey &= ~DC3_CLR_KEY_ENABLE;
+
+		WRITE_VID32 (DF_DISPLAY_CONFIG, df_dcfg);
+        WRITE_REG32 (DC3_COLOR_KEY, vg_ckey);
+		WRITE_REG32 (DC3_COLOR_MASK, (mask & 0xFFFFFF));
+	}
+	else
+	{
+		/* CHROMA KEY - USE DF HARDWARE */
+
+		df_dcfg |= DF_DCFG_VG_CK;
+		vg_ckey &= ~DC3_CLR_KEY_ENABLE;
+
+		WRITE_REG32 (DC3_COLOR_KEY, vg_ckey);
+		WRITE_VID32 (DF_DISPLAY_CONFIG, df_dcfg);
+		WRITE_VID32 (DF_VIDEO_COLOR_KEY, (key & 0xFFFFFF));
+		WRITE_VID32 (DF_VIDEO_COLOR_MASK, (mask & 0xFFFFFF));
+	}
+
+    WRITE_REG32 (DC3_UNLOCK, lock);
+
+	return CIM_STATUS_OK;
+}
+
+/*---------------------------------------------------------------------------
+ * df_set_video_palette
+ *
+ * This routine loads the video hardware palette.  If a NULL pointer is
+ * specified, the palette is bypassed.
+ *--------------------------------------------------------------------------*/
+
+int df_set_video_palette (unsigned long *palette)
+{
+	unsigned long i, entry;
+    unsigned long misc, dcfg;
+
+	/* LOAD GEODE LX VIDEO PALETTE */
+
+	WRITE_VID32 (DF_PALETTE_ADDRESS, 0);
+	for (i = 0; i < 256; i++)
+	{
+		if (palette) entry = palette[i];
+		else entry = i | (i << 8) | (i << 16);
+		WRITE_VID32 (DF_PALETTE_DATA, entry);
+	}
+
+    /* ENABLE THE VIDEO PALETTE */
+    /* Ensure that the video palette has an effect by routing video data */
+    /* through the palette RAM and clearing the 'Bypass Both' bit.       */
+
+    dcfg = READ_VID32 (DF_DISPLAY_CONFIG);
+    misc = READ_VID32 (DF_VID_MISC);
+
+    dcfg |=  DF_DCFG_GV_PAL_BYP;
+    misc &= ~DF_GAMMA_BYPASS_BOTH;
+
+    WRITE_VID32 (DF_DISPLAY_CONFIG, dcfg);
+    WRITE_VID32 (DF_VID_MISC, misc);
+
+	return CIM_STATUS_OK;
+}
+
+/*---------------------------------------------------------------------------
+ * df_set_video_palette_entry
+ *
+ * This routine loads a single entry of the video hardware palette.
+ *--------------------------------------------------------------------------*/
+
+int df_set_video_palette_entry (unsigned long index, unsigned long palette)
+{
+    unsigned long misc, dcfg;
+
+	if (index > 0xFF)
+		return CIM_STATUS_INVALIDPARAMS;
+	
+	/* SET A SINGLE ENTRY */
+
+	WRITE_VID32 (DF_PALETTE_ADDRESS, index);
+	WRITE_VID32 (DF_PALETTE_DATA, palette);
+
+    /* ENABLE THE VIDEO PALETTE */
+    /* Ensure that the video palette has an effect by routing video data */
+    /* through the palette RAM and clearing the 'Bypass Both' bit.       */
+
+    dcfg = READ_VID32 (DF_DISPLAY_CONFIG);
+    misc = READ_VID32 (DF_VID_MISC);
+
+    dcfg |=  DF_DCFG_GV_PAL_BYP;
+    misc &= ~DF_GAMMA_BYPASS_BOTH;
+
+    WRITE_VID32 (DF_DISPLAY_CONFIG, dcfg);
+    WRITE_VID32 (DF_VID_MISC, misc);
+
+	return CIM_STATUS_OK;
+}
+
+/*---------------------------------------------------------------------------
+ * df_configure_video_cursor_color_key
+ *
+ * This routine configures the hardware video cursor color key mechanism.
+ *--------------------------------------------------------------------------*/
+
+int df_configure_video_cursor_color_key (DF_VIDEO_CURSOR_PARAMS *cursor_color_key)
+{	
+	unsigned long key;
+
+	if (cursor_color_key->select_color2 >= 24)
+		return CIM_STATUS_INVALIDPARAMS;
+
+	key = READ_VID32 (DF_CURSOR_COLOR_KEY) & DF_CURSOR_COLOR_KEY_ENABLE;
+	key = key | (cursor_color_key->key & 0xFFFFFF) | (cursor_color_key->select_color2 << 24);
+	
+	WRITE_VID32 (DF_CURSOR_COLOR_KEY, key);
+	WRITE_VID32 (DF_CURSOR_COLOR_MASK, (cursor_color_key->mask & 0xFFFFFF));
+	WRITE_VID32 (DF_CURSOR_COLOR_1, (cursor_color_key->color1 & 0xFFFFFF));
+	WRITE_VID32 (DF_CURSOR_COLOR_2, (cursor_color_key->color2 & 0xFFFFFF));
+
+	return CIM_STATUS_OK;
+}
+
+/*---------------------------------------------------------------------------
+ * df_set_video_cursor_color_key_enable
+ *
+ * This routine enables or disables the video cursor color key.
+ *--------------------------------------------------------------------------*/
+
+int df_set_video_cursor_color_key_enable (int enable)
+{	
+	unsigned long temp = READ_VID32 (DF_CURSOR_COLOR_KEY);
+
+	if (enable) temp |=  DF_CURSOR_COLOR_KEY_ENABLE;
+	else        temp &= ~DF_CURSOR_COLOR_KEY_ENABLE;
+
+	WRITE_VID32 (DF_CURSOR_COLOR_KEY, temp);
+	
+	return CIM_STATUS_OK;
+}
+
+/*---------------------------------------------------------------------------
+ * df_configure_alpha_window
+ *
+ * This routine configures one of the three hardware alpha regions.
+ *--------------------------------------------------------------------------*/
+
+int df_configure_alpha_window (int window, DF_ALPHA_REGION_PARAMS *alpha_data)
+{	
+	unsigned long vsyncend_even, vtotal_even, vactive_even;
+    unsigned long hsyncend, htotal, hactive;
+	unsigned long vsyncend, vtotal, vactive;
+    unsigned long alpha_ctl, pos;	
+	unsigned long hadjust, vadjust;
+    unsigned long y, height;
+	unsigned long xstart, xend;
+	unsigned long ystart, yend;
+    unsigned long x_copy, width_copy;
+    unsigned long y_copy, height_copy;
+    unsigned long scale, src, misc;
+    unsigned long gfxscale, fbactive;
+	unsigned long color;
+	
+	if (window > 2)
+		return CIM_STATUS_INVALIDPARAMS;
+
+	hsyncend = ((READ_REG32 (DC3_H_SYNC_TIMING)   >> 16) & 0xFFF) + 1;
+	vsyncend = ((READ_REG32 (DC3_V_SYNC_TIMING)   >> 16) & 0xFFF) + 1;
+	htotal   = ((READ_REG32 (DC3_H_ACTIVE_TIMING) >> 16) & 0xFFF) + 1;
+	vtotal   = ((READ_REG32 (DC3_V_ACTIVE_TIMING) >> 16) & 0xFFF) + 1;
+	hactive  =  (READ_REG32 (DC3_H_ACTIVE_TIMING) & 0xFFF) + 1;
+	vactive  =  (READ_REG32 (DC3_V_ACTIVE_TIMING) & 0xFFF) + 1;
+
+    /* APPLY THE GRAPHICS SCALE */
+
+    width_copy  = alpha_data->width;
+    height_copy = alpha_data->height;
+    x_copy = alpha_data->x;
+    y_copy = alpha_data->y;
+
+    misc = READ_VID32 (DF_VID_MISC);
+    if (misc & DF_USER_IMPLICIT_SCALING)
+    {
+        gfxscale = READ_REG32 (DC3_GFX_SCALE);
+        fbactive = READ_REG32 (DC3_FB_ACTIVE);
+
+        /* REVERSE ENGINEER THE SCALE FACTOR */
+
+        scale =  gfxscale & 0xFFFF;
+        src   = (fbactive >> 16) + 1;
+        if (scale != 0x4000)
+        {
+            width_copy = width_copy * (((0x4000 * src) / scale) + 1);
+            width_copy /= src;
+            x_copy = x_copy * (((0x4000 * src) / scale) + 1);
+            x_copy /= src;
+        }
+
+        scale =  gfxscale >> 16;
+        src   = (fbactive & 0xFFFF) + 1;
+        if (scale != 0x4000)
+        {
+            height_copy = height_copy * (((0x4000 * src) / scale) + 1);
+            height_copy /= src;
+            y_copy = y_copy * (((0x4000 * src) / scale) + 1);
+            y_copy /= src;
+        }
+    }
+
+	/* SET PRIORITY */
+	/* Priority is the only alpha parameter that is not in a register that */
+	/* can be indexed based on the alpha window number.                    */
+	
+	pos = 16 + (window << 1);
+	alpha_ctl = READ_VID32 (DF_VID_ALPHA_CONTROL) & ~(3L << pos);
+	alpha_ctl |= (alpha_data->priority & 3) << pos;
+	WRITE_VID32 (DF_VID_ALPHA_CONTROL, alpha_ctl);
+
+    /* HANDLE INTERLACED MODES */
+
+    if (READ_REG32 (DC3_IRQ_FILT_CTL) & DC3_IRQFILT_INTL_EN)
+    {
+        vsyncend_even = ((READ_REG32 (DC3_V_SYNC_EVEN)   >> 16) & 0xFFF) + 1;
+        vtotal_even   = ((READ_REG32 (DC3_V_ACTIVE_EVEN) >> 16) & 0xFFF) + 1;
+        vactive_even  =  (READ_REG32 (DC3_V_ACTIVE_EVEN) & 0xFFF) + 1;
+
+        y = y_copy >> 1;
+
+        /* SET Y POSITION FOR ODD FIELD */
+
+        height = (height_copy + 1) >> 1;
+        vadjust = vtotal_even - vsyncend_even + 1;
+
+        ystart = y + vadjust;	
+	    yend   = y + vadjust + height;
+
+        if (yend > (vactive + vadjust))
+		    yend = vactive + vadjust;
+
+        WRITE_VID32 ((DF_ALPHA_YPOS_1 + (window << 5)), (ystart | (yend << 16)));
+
+        /* SET Y POSITION FOR EVEN FIELD */
+
+        height = height_copy >> 1;
+        vadjust = vtotal - vsyncend + 1;
+
+        ystart = y + vadjust;	
+	    yend   = y + vadjust + height;
+
+        if (yend > (vactive_even + vadjust))
+		    yend = vactive_even + vadjust;
+
+        WRITE_VID32 ((DF_VID_ALPHA_Y_EVEN_1 + (window << 3)), (ystart | (yend << 16)));
+    }
+    else
+    {
+        y = y_copy;
+        height = height_copy;
+        vadjust = vtotal - vsyncend + 1;
+
+        ystart = y + vadjust;
+	    yend   = y + vadjust + height;
+
+        if (yend > (vactive + vadjust))
+		    yend = vactive + vadjust;
+
+        WRITE_VID32 ((DF_ALPHA_YPOS_1 + (window << 5)), (ystart | (yend << 16)));
+    }
+
+	/* SET ALPHA X POSITION */
+    /* The x position is the same for both the odd and even fields. */
+
+	hadjust = htotal - hsyncend - 2;
+	
+	xstart = x_copy + hadjust;
+	xend   = x_copy + hadjust + width_copy;
+
+	if (xend > (hactive + hadjust))
+		xend = hactive + hadjust;
+	
+	WRITE_VID32 ((DF_ALPHA_XPOS_1 + (window << 5)), (xstart | (xend << 16)));
+	
+    /* SET COLOR REGISTER */
+
+	color = alpha_data->color & 0xFFFFFF;
+	if (alpha_data->flags & DF_ALPHAFLAG_COLORENABLED)
+		color |= DF_ALPHA_COLOR_ENABLE;
+
+	WRITE_VID32 ((DF_ALPHA_COLOR_1 + (window << 5)), color);
+	
+	/* SET ALPHA VALUE, DELTA AND PER PIXEL */
+
+	alpha_ctl  = READ_VID32 (DF_ALPHA_CONTROL_1 + (window << 5)) & DF_ACTRL_WIN_ENABLE;
+	alpha_ctl |= (alpha_data->alpha_value & 0xFF) | DF_ACTRL_LOAD_ALPHA |
+		        (((unsigned long)alpha_data->delta & 0xFF) << 8);
+	if (alpha_data->flags & DF_ALPHAFLAG_PERPIXELENABLED)
+		alpha_ctl |= DF_ACTRL_PERPIXEL_EN;
+
+	WRITE_VID32 ((DF_ALPHA_CONTROL_1 + (window << 5)), alpha_ctl);
+
+	return CIM_STATUS_OK;
+}
+
+/*---------------------------------------------------------------------------
+ * df_set_alpha_window_enable
+ *
+ * This routine enables or disables one of the three hardware alpha regions.
+ *--------------------------------------------------------------------------*/
+
+int df_set_alpha_window_enable (int window, int enable)
+{	
+	unsigned long alpha_ctl;
+	
+	if (window > 2)
+		return CIM_STATUS_INVALIDPARAMS;
+
+	alpha_ctl = READ_VID32 (DF_ALPHA_CONTROL_1 + (window << 5));
+	if (enable) alpha_ctl |=  DF_ACTRL_WIN_ENABLE;
+	else        alpha_ctl &= ~DF_ACTRL_WIN_ENABLE;
+	WRITE_VID32 ((DF_ALPHA_CONTROL_1 + (window << 5)), alpha_ctl);
+
+	return CIM_STATUS_OK;
+}
+
+/*---------------------------------------------------------------------------
+ * df_set_no_ck_outside_alpha
+ *
+ * This function affects how color/chroma keying is performed inside the video
+ * window.
+ *
+ * If enable is 1, color/chroma key comparison is performed only inside
+ * the enabled alpha windows. Outside the enabled alpha windows, video
+ * is displayed if color keying is enabled, or graphics is displayed if
+ * chroma keying is enabled.
+ * If enable is 0, color/chroma key comparison is performed inside the
+ * entire video window.
+ *--------------------------------------------------------------------------*/
+
+int df_set_no_ck_outside_alpha (int enable)
+{	
+	unsigned long value;
+
+	value = READ_VID32 (DF_VID_ALPHA_CONTROL);
+	if (enable) value |=  DF_NO_CK_OUTSIDE_ALPHA;
+	else        value &= ~DF_NO_CK_OUTSIDE_ALPHA;
+	WRITE_VID32 (DF_VID_ALPHA_CONTROL, value);
+	
+	return CIM_STATUS_OK;
+}
+
+/*---------------------------------------------------------------------------
+ * df_set_video_request
+ *
+ * This routine sets the horizontal (pixel) and vertical (line) video request
+ * values.
+ *--------------------------------------------------------------------------*/
+
+int df_set_video_request (unsigned long x, unsigned long y)
+{	
+	unsigned long htotal, hsyncend;
+	unsigned long vtotal, vsyncend;
+
+	hsyncend = ((READ_REG32 (DC3_H_SYNC_TIMING)   >> 16) & 0xFFF) + 1;
+	vsyncend = ((READ_REG32 (DC3_V_SYNC_TIMING)   >> 16) & 0xFFF) + 1;
+	htotal   = ((READ_REG32 (DC3_H_ACTIVE_TIMING) >> 16) & 0xFFF) + 1;
+	vtotal   = ((READ_REG32 (DC3_V_ACTIVE_TIMING) >> 16) & 0xFFF) + 1;
+
+	/* SET DISPLAY FILTER VIDEO REQUEST */
+	
+	x += htotal - hsyncend - 2;
+	y += vtotal - vsyncend + 1;
+	
+	if (x >= 0x1000 || y >= 0x800)
+		return CIM_STATUS_INVALIDPARAMS;
+	
+	WRITE_VID32(DF_VIDEO_REQUEST, (y | (x << 16)));
+	return CIM_STATUS_OK;
+}
+
+/*---------------------------------------------------------------------------
+ * df_set_output_color_space
+ *
+ * This routine sets the color space used when combining graphics and video.
+ *--------------------------------------------------------------------------*/
+
+int df_set_output_color_space (int color_space)
+{	
+	unsigned long alpha_ctl;
+
+	alpha_ctl = READ_VID32 (DF_VID_ALPHA_CONTROL);
+
+	alpha_ctl &= ~(DF_CSC_GRAPHICS_RGB_TO_YUV | DF_CSC_VIDEO_YUV_TO_RGB |
+		DF_HD_GRAPHICS | DF_YUV_CSC_EN | DF_ALPHA_DRGB);
+
+	/* OUTPUT IS RGB */
+	/* Enable YUV->RGB CSC if necessary and enable alpha output if  */
+	/* requested.                                                   */
+
+	if (color_space == DF_OUTPUT_RGB || color_space == DF_OUTPUT_ARGB)
+	{
+		if (!(alpha_ctl & DF_VIDEO_INPUT_IS_RGB))
+			alpha_ctl |= DF_CSC_VIDEO_YUV_TO_RGB;
+		
+		if (color_space == DF_OUTPUT_ARGB)
+			alpha_ctl |= DF_ALPHA_DRGB;
+	}
+
+	/* OUTPUT IS YUV */
+	/* Enable YUV->YUV CSC if necessary and enable RGB->YUV CSC. */
+	
+	else if (color_space == DF_OUTPUT_SDTV || color_space == DF_OUTPUT_HDTV)
+	{
+		alpha_ctl |= DF_CSC_GRAPHICS_RGB_TO_YUV;
+
+		if ( ((alpha_ctl & DF_HD_VIDEO) && color_space == DF_OUTPUT_SDTV) ||
+		    (!(alpha_ctl & DF_HD_VIDEO) && color_space == DF_OUTPUT_HDTV))
+		{
+			alpha_ctl |= DF_YUV_CSC_EN;
+		}
+
+		if (color_space == DF_OUTPUT_HDTV)
+			alpha_ctl |= DF_HD_GRAPHICS;		
+	}
+	else
+		return CIM_STATUS_INVALIDPARAMS;
+
+	WRITE_VID32 (DF_VID_ALPHA_CONTROL, alpha_ctl);
+
+	return CIM_STATUS_OK;
+}
+
+/*---------------------------------------------------------------------------
+ * df_set_output_path
+ *
+ * This routine changes the current output path in the display filter.
+ *--------------------------------------------------------------------------*/
+
+int df_set_output_path (int format)
+{
+    unsigned long panel_tim2, panel_pm;
+    unsigned long output = 0;
+    Q_WORD msr_value;
+
+    msr_read64 (MSR_DEVICE_GEODELX_DF, MSR_GEODELINK_CONFIG, &msr_value);
+    msr_value.low &= ~(DF_SIMULTANEOUS_CRT_FP | DF_CONFIG_OUTPUT_MASK);
+    panel_tim2 = READ_VID32 (DF_VIDEO_PANEL_TIM2);
+    panel_pm   = READ_VID32 (DF_POWER_MANAGEMENT);
+
+    if (format == DF_DISPLAY_CRT)
+    {
+        /* SiBZ #4188 */
+        /* When CRT output is selected, the DF drives the DISP_EN signal   */
+        /* with the CRT display enable.  As a consequence, systems that    */
+        /* wire the DISP_EN signal to the TFT backlight control will not   */
+        /* be able to set CRT-only output without leaving the backlight    */
+        /* enabled.  To workaround this issue, we are setting simultaneous */
+        /* TFT/CRT and disabling the TFT logic.  The only caveat to this   */
+        /* is that some TFT pins are shared with VIP 601 pins.  VIP 601    */
+        /* will thus not work when in this pseudo-CRT mode.  To address    */
+        /* THAT issue, normal CRT mode sets (in cim_vg.c) will set CRT     */
+        /* as the DF output format.  This will allow VIP 601 on CRT-only   */
+        /* systems without a TFT attached.                                 */
+
+        panel_pm &= ~DF_PM_PANEL_ON;
+        panel_tim2 |= DF_PMTIM2_TFT_PASSHTHROUGH;
+        output = DF_OUTPUT_PANEL | DF_SIMULTANEOUS_CRT_FP;
+    }
+    else if (format == DF_DISPLAY_FP || format == DF_DISPLAY_CRT_FP)
+    {
+        panel_pm |= DF_PM_PANEL_ON;
+        panel_tim2 &= ~DF_PMTIM2_TFT_PASSHTHROUGH;
+
+        if (format == DF_DISPLAY_FP)
+            output = DF_OUTPUT_PANEL;
+        else if (format == DF_DISPLAY_CRT_FP)
+            output = DF_OUTPUT_PANEL | DF_SIMULTANEOUS_CRT_FP;
+    }
+    else
+    {
+        switch (format)
+        {
+            case DF_DISPLAY_VOP:       output = DF_OUTPUT_VOP;                            break;
+            case DF_DISPLAY_DRGB:      output = DF_OUTPUT_DRGB;                           break;
+            case DF_DISPLAY_CRT_DRGB:  output = DF_OUTPUT_DRGB | DF_SIMULTANEOUS_CRT_FP;  break;
+            default:
+                return CIM_STATUS_INVALIDPARAMS;
+        }
+    }
+    msr_value.low |= output;
+    msr_write64 (MSR_DEVICE_GEODELX_DF, MSR_GEODELINK_CONFIG, &msr_value);
+    WRITE_VID32 (DF_VIDEO_PANEL_TIM2, panel_tim2);
+    WRITE_VID32 (DF_POWER_MANAGEMENT, panel_pm);
+
+    return CIM_STATUS_OK;
+}
+
+/*---------------------------------------------------------------------------
+ * df_test_video_flip_status
+ *
+ * This routine tests if a new video offset has been latched.
+ *--------------------------------------------------------------------------*/
+
+unsigned long df_test_video_flip_status (void)
+{	
+	return (READ_REG32 (DC3_LINE_CNT_STATUS) & DC3_LNCNT_VFLIP);
+}
+
+/*---------------------------------------------------------------------------
+ * df_save_state
+ *
+ * This routine saves all persistent DF state information.
+ *---------------------------------------------------------------------------*/
+
+int df_save_state (DF_SAVE_RESTORE *df_state)
+{
+    unsigned long i;
+
+    /* READ ALL DF REGISTERS */
+
+    df_state->vcfg               = READ_VID32 (DF_VIDEO_CONFIG);
+    df_state->dcfg               = READ_VID32 (DF_DISPLAY_CONFIG);
+    df_state->video_x            = READ_VID32 (DF_VIDEO_X_POS);
+    df_state->video_y            = READ_VID32 (DF_VIDEO_Y_POS);
+    df_state->video_scaler       = READ_VID32 (DF_VIDEO_SCALER);
+    df_state->video_color_key    = READ_VID32 (DF_VIDEO_COLOR_KEY);
+    df_state->video_color_mask   = READ_VID32 (DF_VIDEO_COLOR_MASK);
+    df_state->sat_limit          = READ_VID32 (DF_SATURATION_LIMIT);
+    df_state->vid_misc           = READ_VID32 (DF_VID_MISC);
+    df_state->video_yscale       = READ_VID32 (DF_VIDEO_YSCALE);
+    df_state->video_xscale       = READ_VID32 (DF_VIDEO_XSCALE);
+    df_state->vid_alpha_control  = READ_VID32 (DF_VID_ALPHA_CONTROL);
+    df_state->cursor_key         = READ_VID32 (DF_CURSOR_COLOR_KEY);
+    df_state->cursor_mask        = READ_VID32 (DF_CURSOR_COLOR_MASK);
+    df_state->cursor_color1      = READ_VID32 (DF_CURSOR_COLOR_1);
+    df_state->cursor_color2      = READ_VID32 (DF_CURSOR_COLOR_2);
+    df_state->alpha_xpos1        = READ_VID32 (DF_ALPHA_XPOS_1);
+    df_state->alpha_ypos1        = READ_VID32 (DF_ALPHA_YPOS_1);
+    df_state->alpha_color1       = READ_VID32 (DF_ALPHA_COLOR_1);
+    df_state->alpha_control1     = READ_VID32 (DF_ALPHA_CONTROL_1);
+    df_state->alpha_xpos2        = READ_VID32 (DF_ALPHA_XPOS_2);
+    df_state->alpha_ypos2        = READ_VID32 (DF_ALPHA_YPOS_2);
+    df_state->alpha_color2       = READ_VID32 (DF_ALPHA_COLOR_2);
+    df_state->alpha_control2     = READ_VID32 (DF_ALPHA_CONTROL_2);
+    df_state->alpha_xpos3        = READ_VID32 (DF_ALPHA_XPOS_3);
+    df_state->alpha_ypos3        = READ_VID32 (DF_ALPHA_YPOS_3);
+    df_state->alpha_color3       = READ_VID32 (DF_ALPHA_COLOR_3);
+    df_state->alpha_control3     = READ_VID32 (DF_ALPHA_CONTROL_3);
+    df_state->vid_request        = READ_VID32 (DF_VIDEO_REQUEST);
+    df_state->vid_ypos_even      = READ_VID32 (DF_VID_YPOS_EVEN);
+    df_state->alpha_ypos_even1   = READ_VID32 (DF_VID_ALPHA_Y_EVEN_1);
+    df_state->alpha_ypos_even2   = READ_VID32 (DF_VID_ALPHA_Y_EVEN_2);
+    df_state->alpha_ypos_even3   = READ_VID32 (DF_VID_ALPHA_Y_EVEN_3);
+    df_state->panel_tim1         = READ_VID32 (DF_VIDEO_PANEL_TIM1);
+    df_state->panel_tim2         = READ_VID32 (DF_VIDEO_PANEL_TIM2);
+    df_state->panel_pm           = READ_VID32 (DF_POWER_MANAGEMENT);
+    df_state->panel_dither       = READ_VID32 (DF_DITHER_CONTROL);
+
+    /* READ DF PALETTE */
+
+    WRITE_VID32 (DF_PALETTE_ADDRESS, 0);
+	for (i = 0; i < 256; i++)
+        df_state->palette[i] = READ_VID32 (DF_PALETTE_DATA);
+
+    /* READ FILTER COEFFICIENTS */
+
+    for (i = 0; i < 512; i++)
+        df_state->coefficients[i] = READ_VID32 (DF_COEFFICIENT_BASE + (i << 2));
+
+    /* READ ALL DF MSRS */
+
+    msr_read64 (MSR_DEVICE_GEODELX_DF, MSR_GEODELINK_CAP,    &(df_state->msr_cap));
+    msr_read64 (MSR_DEVICE_GEODELX_DF, MSR_GEODELINK_CONFIG, &(df_state->msr_config));
+    msr_read64 (MSR_DEVICE_GEODELX_DF, MSR_GEODELINK_SMI,    &(df_state->msr_smi));
+    msr_read64 (MSR_DEVICE_GEODELX_DF, MSR_GEODELINK_ERROR,  &(df_state->msr_error));
+    msr_read64 (MSR_DEVICE_GEODELX_DF, MSR_GEODELINK_PM,     &(df_state->msr_pm));
+    msr_read64 (MSR_DEVICE_GEODELX_DF, MSR_GEODELINK_DIAG,   &(df_state->msr_diag));
+    msr_read64 (MSR_DEVICE_GEODELX_DF, DF_MBD_MSR_DIAG_DF,   &(df_state->msr_df_diag));
+    msr_read64 (MSR_DEVICE_GEODELX_DF, DF_MSR_PAD_SEL,       &(df_state->msr_pad_sel));
+
+    return CIM_STATUS_OK;
+}
+
+/*---------------------------------------------------------------------------
+ * df_restore_state
+ *
+ * This routine restores all persistent DF state information.
+ *---------------------------------------------------------------------------*/
+
+int df_restore_state (DF_SAVE_RESTORE *df_state)
+{
+    unsigned long i;
+
+    /* CLEAR VCFG AND DCFG */
+
+    WRITE_VID32 (DF_VIDEO_CONFIG,   0);
+    WRITE_VID32 (DF_DISPLAY_CONFIG, 0);
+
+    /* RESTORE DF MSRS */
+
+    msr_write64 (MSR_DEVICE_GEODELX_DF, MSR_GEODELINK_CAP,    &(df_state->msr_cap));
+    msr_write64 (MSR_DEVICE_GEODELX_DF, MSR_GEODELINK_CONFIG, &(df_state->msr_config));
+    msr_write64 (MSR_DEVICE_GEODELX_DF, MSR_GEODELINK_SMI,    &(df_state->msr_smi));
+    msr_write64 (MSR_DEVICE_GEODELX_DF, MSR_GEODELINK_ERROR,  &(df_state->msr_error));
+    msr_write64 (MSR_DEVICE_GEODELX_DF, MSR_GEODELINK_PM,     &(df_state->msr_pm));
+    msr_write64 (MSR_DEVICE_GEODELX_DF, MSR_GEODELINK_DIAG,   &(df_state->msr_diag));
+    msr_write64 (MSR_DEVICE_GEODELX_DF, DF_MBD_MSR_DIAG_DF,   &(df_state->msr_df_diag));
+    msr_write64 (MSR_DEVICE_GEODELX_DF, DF_MSR_PAD_SEL,       &(df_state->msr_pad_sel));
+
+    /* RESTORE ALL DF REGISTERS */
+
+    WRITE_VID32 (DF_VIDEO_X_POS,           df_state->video_x);
+    WRITE_VID32 (DF_VIDEO_Y_POS,           df_state->video_y);
+    WRITE_VID32 (DF_VIDEO_SCALER,          df_state->video_scaler);
+    WRITE_VID32 (DF_VIDEO_COLOR_KEY,       df_state->video_color_key);
+    WRITE_VID32 (DF_VIDEO_COLOR_MASK,      df_state->video_color_mask);
+    WRITE_VID32 (DF_SATURATION_LIMIT,      df_state->sat_limit);
+    WRITE_VID32 (DF_VID_MISC,              df_state->vid_misc);
+    WRITE_VID32 (DF_VIDEO_YSCALE,          df_state->video_yscale);
+    WRITE_VID32 (DF_VIDEO_XSCALE,          df_state->video_xscale);
+    WRITE_VID32 (DF_VID_ALPHA_CONTROL,     df_state->vid_alpha_control);
+    WRITE_VID32 (DF_CURSOR_COLOR_KEY,      df_state->cursor_key);
+    WRITE_VID32 (DF_CURSOR_COLOR_MASK,     df_state->cursor_mask);
+    WRITE_VID32 (DF_CURSOR_COLOR_1,        df_state->cursor_color1);
+    WRITE_VID32 (DF_CURSOR_COLOR_2,        df_state->cursor_color2);
+    WRITE_VID32 (DF_ALPHA_XPOS_1,          df_state->alpha_xpos1);
+    WRITE_VID32 (DF_ALPHA_YPOS_1,          df_state->alpha_ypos1);
+    WRITE_VID32 (DF_ALPHA_COLOR_1,         df_state->alpha_color1);
+    WRITE_VID32 (DF_ALPHA_CONTROL_1,       df_state->alpha_control1);
+    WRITE_VID32 (DF_ALPHA_XPOS_2,          df_state->alpha_xpos2);
+    WRITE_VID32 (DF_ALPHA_YPOS_2,          df_state->alpha_ypos2);
+    WRITE_VID32 (DF_ALPHA_COLOR_2,         df_state->alpha_color2);
+    WRITE_VID32 (DF_ALPHA_CONTROL_2,       df_state->alpha_control1);
+    WRITE_VID32 (DF_ALPHA_XPOS_3,          df_state->alpha_xpos3);
+    WRITE_VID32 (DF_ALPHA_YPOS_3,          df_state->alpha_ypos3);
+    WRITE_VID32 (DF_ALPHA_COLOR_3,         df_state->alpha_color3);
+    WRITE_VID32 (DF_ALPHA_CONTROL_3,       df_state->alpha_control3);
+    WRITE_VID32 (DF_VIDEO_REQUEST,         df_state->vid_request);
+    WRITE_VID32 (DF_VID_YPOS_EVEN,         df_state->vid_ypos_even);
+    WRITE_VID32 (DF_VID_ALPHA_Y_EVEN_1,    df_state->alpha_ypos_even1);
+    WRITE_VID32 (DF_VID_ALPHA_Y_EVEN_2,    df_state->alpha_ypos_even2);
+    WRITE_VID32 (DF_VID_ALPHA_Y_EVEN_3,    df_state->alpha_ypos_even3);
+    WRITE_VID32 (DF_VIDEO_PANEL_TIM1,      df_state->panel_tim1);
+    WRITE_VID32 (DF_VIDEO_PANEL_TIM2,      df_state->panel_tim2);
+    WRITE_VID32 (DF_POWER_MANAGEMENT,      df_state->panel_pm);
+    WRITE_VID32 (DF_DITHER_CONTROL,        df_state->panel_dither);
+
+    /* RESTORE DF PALETTE */
+
+    WRITE_VID32 (DF_PALETTE_ADDRESS, 0);
+	for (i = 0; i < 256; i++)
+        WRITE_VID32 (DF_PALETTE_DATA, df_state->palette[i]);
+
+    /* RESTORE FILTER COEFFICIENTS */
+
+    for (i = 0; i < 512; i++)
+        WRITE_VID32 (DF_COEFFICIENT_BASE + (i << 2), df_state->coefficients[i]);
+
+    /* RESTORE DCFG AND VCFG */
+
+    WRITE_VID32 (DF_DISPLAY_CONFIG, df_state->dcfg);
+    WRITE_VID32 (DF_VIDEO_CONFIG, df_state->vcfg);
+
+    return CIM_STATUS_OK;
+}
+
+/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ * CIMARRON DF READ ROUTINES
+ * These routines are included for use in diagnostics or when debugging.  They
+ * can be optionally excluded from a project.
+ *+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
+
+#if CIMARRON_INCLUDE_DF_READ_ROUTINES
+
+/*---------------------------------------------------------------------------
+ * df_read_composite_crc
+ *
+ * This routine reads the CRC of the combination of graphics/video data.  This
+ * CRC checks data immediately before the CRT DACs.
+ *---------------------------------------------------------------------------*/
+
+unsigned long df_read_composite_crc (int crc_source)
+{
+    Q_WORD msr_value;
+	unsigned long crc;
+    unsigned long interlaced;
+    unsigned long line, field;
+    unsigned long timeout = 1000;
+
+	if (!(READ_REG32 (DC3_DISPLAY_CFG) & DC3_DCFG_TGEN))
+		return 0xFFFFFFFF;
+
+	/* ENABLE 32-BIT CRCS */
+
+	msr_read64 (MSR_DEVICE_GEODELX_DF, DF_MBD_MSR_DIAG_DF, &msr_value);
+	msr_value.low |= DF_DIAG_32BIT_CRC;
+	msr_write64 (MSR_DEVICE_GEODELX_DF, DF_MBD_MSR_DIAG_DF, &msr_value);
+
+	/* RESET THE CRC */
+
+    WRITE_VID32 (DF_VID_CRC, 0);
+
+    /* WAIT FOR THE RESET TO BE LATCHED */
+
+    while ((READ_VID32 (DF_VID_CRC32) != 0x00000001) && timeout)
+        timeout--;
+
+    /* WAIT FOR THE CORRECT FIELD */
+    /* We use the VG line count and field indicator to determine when */
+    /* to kick off a CRC.                                             */
+
+    if (crc_source & DF_CRC_SOURCE_EVEN) field = 0;
+    else                                 field = DC3_LNCNT_EVEN_FIELD;
+
+    if ((interlaced = (READ_REG32 (DC3_IRQ_FILT_CTL) & DC3_IRQFILT_INTL_EN)))
+    {
+        /* WAIT FOR THE BEGINNING OF THE FIELD (LINE 1-5) */
+        /* Note that we wait for the field to be odd when CRCing the even */
+        /* field and vice versa.  This is because the CRC will not begin  */
+        /* until the following field.                                     */
+
+        do
+        {
+            line = READ_REG32 (DC3_LINE_CNT_STATUS);
+        } while ((line & DC3_LNCNT_EVEN_FIELD) != field    ||
+                ((line & DC3_LNCNT_V_LINE_CNT) >> 16) < 10 ||
+                ((line & DC3_LNCNT_V_LINE_CNT) >> 16) > 15);
+    }
+    else
+    {
+        /* NON-INTERLACED - EVEN FIELD CRCS ARE INVALID */
+
+        if (crc_source & DF_CRC_SOURCE_EVEN)
+            return 0xFFFFFFFF;
+    }
+
+    /* ENABLE THE CRC */
+
+	WRITE_VID32 (DF_VID_CRC, 1);
+
+	/* WAIT FOR THE CRC TO BE COMPLETED */
+	
+    while (!(READ_VID32 (DF_VID_CRC) & 4))
+        ;
+	
+	crc = READ_VID32 (DF_VID_CRC32);
+
+	return crc;
+}
+
+/*---------------------------------------------------------------------------
+ * df_read_composite_window_crc
+ *
+ * This routine reads the CRC of a rectangular subsection of the combination
+ * of graphics/video data.
+ *---------------------------------------------------------------------------*/
+
+unsigned long df_read_composite_window_crc (unsigned long x, unsigned long y,
+	unsigned long width, unsigned long height, int source)
+{
+    Q_WORD msr_value;
+    unsigned long interlaced;
+    unsigned long line, field;
+	unsigned long crc = 0;
+	unsigned long hsyncend, htotal, hsyncstart;
+	unsigned long vsyncend, vtotal, vsyncstart;
+    unsigned long hblankstart, hactive;
+    unsigned long vblankstart, vactive;
+
+    hsyncend    = ((READ_REG32 (DC3_H_SYNC_TIMING)   >> 16) & 0xFFF) + 1;
+    htotal      = ((READ_REG32 (DC3_H_ACTIVE_TIMING) >> 16) & 0xFFF) + 1;
+    hsyncstart  =  (READ_REG32 (DC3_H_SYNC_TIMING) & 0xFFF) + 1;
+    hactive     =  (READ_REG32 (DC3_H_ACTIVE_TIMING) & 0xFFF) + 1;
+    hblankstart =  (READ_REG32 (DC3_H_BLANK_TIMING)  & 0xFFF) + 1;
+    if ((interlaced = (READ_REG32 (DC3_IRQ_FILT_CTL) & DC3_IRQFILT_INTL_EN)) &&
+        !(source & DF_CRC_SOURCE_EVEN))
+    {
+        vsyncend    = ((READ_REG32 (DC3_V_SYNC_EVEN)   >> 16) & 0xFFF) + 1;
+	    vtotal      = ((READ_REG32 (DC3_V_ACTIVE_EVEN) >> 16) & 0xFFF) + 1;
+	    vsyncstart  =  (READ_REG32 (DC3_V_SYNC_EVEN) & 0xFFF) + 1;
+        vactive     =  (READ_REG32 (DC3_V_ACTIVE_EVEN) & 0xFFF) + 1;
+        vblankstart =  (READ_REG32 (DC3_V_BLANK_EVEN)  & 0xFFF) + 1;
+    }
+    else
+    {	
+	    vsyncend    = ((READ_REG32 (DC3_V_SYNC_TIMING)   >> 16) & 0xFFF) + 1;
+	    vtotal      = ((READ_REG32 (DC3_V_ACTIVE_TIMING) >> 16) & 0xFFF) + 1;
+	    vsyncstart  =  (READ_REG32 (DC3_V_SYNC_TIMING) & 0xFFF) + 1;
+        vactive     =  (READ_REG32 (DC3_V_ACTIVE_TIMING) & 0xFFF) + 1;
+        vblankstart =  (READ_REG32 (DC3_V_BLANK_TIMING)  & 0xFFF) + 1;
+    }
+
+    /* TIMINGS MUST BE ACTIVE */
+
+	if (!(READ_REG32 (DC3_DISPLAY_CFG) & DC3_DCFG_TGEN))
+		return 0xFFFFFFFF;
+
+    /* DISABLE GLCP ACTIONS */
+
+    msr_value.low  = 0;
+    msr_value.high = 0;
+    msr_write64 (MSR_DEVICE_GEODELX_GLCP, GLCP_DIAGCTL, &msr_value);
+
+	/* ENABLE HW CLOCK GATING AND SET GLCP CLOCK TO DOT CLOCK */
+
+	msr_value.low = 5;
+	msr_write64 (MSR_DEVICE_GEODELX_GLCP, MSR_GEODELINK_PM, &msr_value);
+	msr_value.low = 0;
+	msr_write64 (MSR_DEVICE_GEODELX_GLCP, GLCP_DBGCLKCTL, &msr_value);
+	msr_value.low = 3;
+	msr_write64 (MSR_DEVICE_GEODELX_GLCP, GLCP_DBGCLKCTL, &msr_value);
+
+    /* USE H4 FUNCTION A FOR HSYNC AND H4 FUNCTION B FOR NOT HSYNC */
+    /* HSYNC is bit 30 for the DF                                  */
+
+    msr_value.high = 0x00000001;
+    msr_value.low  = 0xE0000FF0;
+    msr_write64 (MSR_DEVICE_GEODELX_GLCP, GLCP_H0CTL + 4, &msr_value);
+
+    /* USE H3 FUNCTION A FOR VSYNC AND H3 FUNCTION B FOR NOT VSYNC */
+    /* VSYNC is bit 54 for VG and bit 29 for DF                    */
+
+    msr_value.high = 0x00000000;
+    msr_value.low  = 0x001D55AA;
+    msr_write64 (MSR_DEVICE_GEODELX_GLCP, GLCP_H0CTL + 3, &msr_value);
+
+    /* M4 (XSTATE = 00 AND VSYNC HIGH) */
+    /* Goto state 01                   */
+    /* Note: VSync = H3A               */
+
+    msr_value.high = 0x00000001;
+    msr_value.low  = 0x000000A0;
+    msr_write64 (MSR_DEVICE_GEODELX_GLCP, GLCP_SETM0CTL + 4, &msr_value);
+
+    /* N0 (XSTATE = 01 AND VSYNC LOW) */
+    /* Goto state 02                  */
+    /* Note: VSync low = H3B          */
+
+    msr_value.high = 0x00040000;
+    msr_value.low  = 0x000000C0;
+    msr_write64 (MSR_DEVICE_GEODELX_GLCP, GLCP_SETN0CTL, &msr_value);
+
+    /* M5 (XSTATE = 10 AND VSYNC HIGH) */
+    /* Goto state 11                   */
+
+    msr_value.high = 0x00000001;
+    msr_value.low  = 0x00000120;
+    msr_write64 (MSR_DEVICE_GEODELX_GLCP, GLCP_SETM0CTL + 5, &msr_value);
+
+    /* N1 (XSTATE = 10 and HSYNC LOW) */
+    /* Increment H. Counter           */
+    /* Note: HSync = H4               */
+
+    msr_value.high = 0x00080000;
+    msr_value.low  = 0x00000120;
+    msr_write64 (MSR_DEVICE_GEODELX_GLCP, GLCP_SETN0CTL + 1, &msr_value);
+
+    /* M0 (XSTATE = 10 and H. COUNTER == LIMIT)  */
+    /* Clear H. Counter and increment V. Counter */
+
+    msr_value.high = 0x00000000;
+    msr_value.low  = 0x00000122;
+    msr_write64 (MSR_DEVICE_GEODELX_GLCP, GLCP_SETM0CTL, &msr_value);
+
+    /* N4 (XSTATE = 10 && CMP0 <= H. COUNTER <= CMP1 && CMP2 <= V. COUNTER <= CMP3) */
+    /* CRC into REGB                                                                */
+
+    msr_value.high = 0x00000000;
+    msr_value.low  = 0x10C20120;
+    msr_write64 (MSR_DEVICE_GEODELX_GLCP, GLCP_SETN0CTL + 4, &msr_value);
+
+    /* COMPARATOR 0 VALUE                                   */
+    /* Value = xstart + (htotal - hsync_end) - 1            */
+    /* The value will be adjusted for a border if necessary */
+
+    msr_value.low  = x + htotal - hsyncend - 1;
+    if (READ_REG32 (DC3_DISPLAY_CFG) & DC3_DCFG_DCEN)
+        msr_value.low -= hblankstart - hactive;
+    msr_value.low--;
+    msr_write64 (MSR_DEVICE_GEODELX_GLCP, GLCP_CMPVAL0, &msr_value);
+
+    /* COMPARATOR 1 VALUE                                    */
+    /* Value = xstart + (htotal - hsync_end - 1) - 1 + width */
+
+    msr_value.low  += width - 1;
+    msr_write64 (MSR_DEVICE_GEODELX_GLCP, GLCP_CMPVAL0 + 2, &msr_value);
+
+    /* COMPARATOR 2 VALUE                 */
+    /* Value = ystart + vtotal - vsyncend */
+
+    msr_value.low  = (y + vtotal - vsyncend) << 16;
+    if (READ_REG32 (DC3_DISPLAY_CFG) & DC3_DCFG_DCEN)
+        msr_value.low -= (vblankstart - vactive) << 16;
+    msr_write64 (MSR_DEVICE_GEODELX_GLCP, GLCP_CMPVAL0 + 4, &msr_value);
+
+    /* COMPARATOR 3 VALUE                              */
+    /* Value = ystart + vtotal - vsyncend + height - 1 */
+
+    msr_value.low  += (height - 1) << 16;
+    msr_write64 (MSR_DEVICE_GEODELX_GLCP, GLCP_CMPVAL0 + 6, &msr_value);
+
+    /* COMPARATOR MASKS */
+    /* Comparators 0 and 1 refer to lower 16 bits of RegB */
+
+    msr_value.low = 0x0000FFFF;
+    msr_write64 (MSR_DEVICE_GEODELX_GLCP, GLCP_CMPMASK0, &msr_value);
+    msr_write64 (MSR_DEVICE_GEODELX_GLCP, GLCP_CMPMASK0 + 2, &msr_value);
+
+    /* Comparators 2 and 3 refer to upper 16 bits of RegB */
+
+    msr_value.low = 0xFFFF0000;
+    msr_write64 (MSR_DEVICE_GEODELX_GLCP, GLCP_CMPMASK0 + 4, &msr_value);
+    msr_write64 (MSR_DEVICE_GEODELX_GLCP, GLCP_CMPMASK0 + 6, &msr_value);
+
+    /* SET REGB MASK                                                */
+    /* We set the mask such that all only 24 bits of data are CRCed */
+
+    msr_value.low = 0x00FFFFFF;
+    msr_write64 (MSR_DEVICE_GEODELX_GLCP, GLCP_REGBMASK, &msr_value);
+
+    /* SET REGA LIMITS                              */
+    /* Lower counter uses htotal - sync_time - 1.   */
+    /* Upper counter is 0xFFFF to prevent rollover. */
+
+    msr_value.low = 0xFFFF0000 | (htotal - (hsyncend - hsyncstart) - 1);
+    msr_write64 (MSR_DEVICE_GEODELX_GLCP, GLCP_REGAVAL, &msr_value);
+
+    /* ACTIONS */
+
+    /* STATE 00->01 (SET 4M) */
+
+    msr_value.low = 0x000C0000;
+    msr_write64 (MSR_DEVICE_GEODELX_GLCP, GLCP_ACTION0 + 14, &msr_value);
+
+    /* STATE 01->10 (SET 0N) */
+
+    msr_value.low = 0x0000000A;
+    msr_write64 (MSR_DEVICE_GEODELX_GLCP, GLCP_ACTION0 + 15, &msr_value);
+
+    /* STATE 10->11 (SET 5M) */
+
+    msr_value.low = 0x00C00000;
+    msr_write64 (MSR_DEVICE_GEODELX_GLCP, GLCP_ACTION0 + 16, &msr_value);
+
+    /* CLEAR REGA WHEN TRANSITIONING TO STATE 10                 */
+    /* Do not clear RegB as the initial value must be 0x00000001 */
+
+    msr_value.low = 0x0000000A;
+    msr_write64 (MSR_DEVICE_GEODELX_GLCP, GLCP_ACTION0, &msr_value);
+
+    /* REGISTER ACTION 1 */
+    /* CRC into RegB if cmp0 <= h.counter <= cmp1 && cmp2 <= v. counter < cmp3 && 7 xstate = 10 8 */
+    /* Increment h.counter if xstate = 10 and HSync is low.                                       */
+
+    msr_value.low = 0x000A00A0;
+    msr_write64 (MSR_DEVICE_GEODELX_GLCP, GLCP_ACTION0 + 1, &msr_value);
+
+    /* REGISTER ACTION 2            */
+    /* Increment V. Counter in REGA */
+
+    msr_value.low = 0x0000000C;
+    msr_write64 (MSR_DEVICE_GEODELX_GLCP, GLCP_ACTION0 + 2, &msr_value);
+
+    /* SET REGB TO 0x00000001 */
+
+    msr_value.low = 0x00000001;
+    msr_write64 (MSR_DEVICE_GEODELX_GLCP, GLCP_REGB, &msr_value);
+
+    /* SET XSTATE TO 0 */
+
+    msr_value.low = 0x00000000;
+    msr_write64 (MSR_DEVICE_GEODELX_GLCP, GLCP_XSTATE, &msr_value);
+
+    /* CLEAR ALL OTHER ACTIONS */
+	/* This prevents side-effects from previous accesses to the GLCP */
+	/* debug logic.                                                  */
+
+	msr_value.low  = 0x00000000;
+	msr_value.high = 0x00000000;
+	msr_write64 (MSR_DEVICE_GEODELX_GLCP, GLCP_ACTION0 + 3, &msr_value);
+	msr_write64 (MSR_DEVICE_GEODELX_GLCP, GLCP_ACTION0 + 4, &msr_value);
+	msr_write64 (MSR_DEVICE_GEODELX_GLCP, GLCP_ACTION0 + 5, &msr_value);
+	msr_write64 (MSR_DEVICE_GEODELX_GLCP, GLCP_ACTION0 + 6, &msr_value);
+	msr_write64 (MSR_DEVICE_GEODELX_GLCP, GLCP_ACTION0 + 7, &msr_value);
+	msr_write64 (MSR_DEVICE_GEODELX_GLCP, GLCP_ACTION0 + 8, &msr_value);
+	msr_write64 (MSR_DEVICE_GEODELX_GLCP, GLCP_ACTION0 + 9, &msr_value);
+	msr_write64 (MSR_DEVICE_GEODELX_GLCP, GLCP_ACTION0 + 10, &msr_value);
+	msr_write64 (MSR_DEVICE_GEODELX_GLCP, GLCP_ACTION0 + 11, &msr_value);
+	msr_write64 (MSR_DEVICE_GEODELX_GLCP, GLCP_ACTION0 + 12, &msr_value);
+	msr_write64 (MSR_DEVICE_GEODELX_GLCP, GLCP_ACTION0 + 13, &msr_value);
+	msr_write64 (MSR_DEVICE_GEODELX_GLCP, GLCP_ACTION0 + 17, &msr_value);
+	msr_write64 (MSR_DEVICE_GEODELX_GLCP, GLCP_ACTION0 + 18, &msr_value);
+	msr_write64 (MSR_DEVICE_GEODELX_GLCP, GLCP_ACTION0 + 19, &msr_value);
+	msr_write64 (MSR_DEVICE_GEODELX_GLCP, GLCP_ACTION0 + 20, &msr_value);
+
+    /* WAIT FOR THE CORRECT FIELD */
+    /* We use the VG line count and field indicator to determine when */
+    /* to kick off a CRC.                                             */
+
+    if (source & DF_CRC_SOURCE_EVEN) field = 0;
+    else                             field = DC3_LNCNT_EVEN_FIELD;
+
+    if (interlaced)
+    {
+        /* WAIT FOR THE BEGINNING OF THE FIELD (LINE 1-5) */
+        /* Note that we wait for the field to be odd when CRCing the even */
+        /* field and vice versa.  This is because the CRC will not begin  */
+        /* until the following field.                                     */
+
+        do
+        {
+            line = READ_REG32 (DC3_LINE_CNT_STATUS);
+        } while ((line & DC3_LNCNT_EVEN_FIELD) != field    ||
+                ((line & DC3_LNCNT_V_LINE_CNT) >> 16) < 1 ||
+                ((line & DC3_LNCNT_V_LINE_CNT) >> 16) > 5);
+    }
+    else
+    {
+        /* NON-INTERLACED - EVEN FIELD CRCS ARE INVALID */
+
+        if (source & DF_CRC_SOURCE_EVEN)
+            return 0xFFFFFFFF;
+    }
+
+    /* CONFIGURE DISPLAY FILTER TO LOAD DATA ONTO LOWER 32-BITS */
+
+	msr_value.high = 0;
+    msr_value.low  = 0x0000800B;
+	msr_write64 (MSR_DEVICE_GEODELX_DF, MSR_GEODELINK_DIAG, &msr_value);
+
+    /* CONFIGURE DIAG CONTROL */
+    /* Set RegA action1 to increment lower 16 bits and clear at limit. (5)      */
+    /* Set RegA action2 to increment upper 16 bits. (6)                         */
+    /* Set RegB action1 to CRC32 (1)                                            */
+    /* Set all comparators to REGA override (0,1 lower mbus, 2,3 upper mbus)    */
+    /* Enable all actions                                                       */
+
+    msr_value.low = 0x80EA20A0;
+    msr_write64 (MSR_DEVICE_GEODELX_GLCP, GLCP_DIAGCTL, &msr_value);
+	
+	/* DELAY TWO FRAMES */
+
+	while (READ_REG32 (DC3_LINE_CNT_STATUS) & DC3_LNCNT_VNA);
+	while (!(READ_REG32 (DC3_LINE_CNT_STATUS) & DC3_LNCNT_VNA));
+	while (READ_REG32 (DC3_LINE_CNT_STATUS) & DC3_LNCNT_VNA);
+	while (!(READ_REG32 (DC3_LINE_CNT_STATUS) & DC3_LNCNT_VNA));
+	while (READ_REG32 (DC3_LINE_CNT_STATUS) & DC3_LNCNT_VNA);
+
+	/* VERIFY THAT XSTATE = 11 */
+
+	msr_read64 (MSR_DEVICE_GEODELX_GLCP, GLCP_XSTATE, &msr_value);
+	if ((msr_value.low & 3) == 3)
+	{
+		msr_read64 (MSR_DEVICE_GEODELX_GLCP, GLCP_REGB, &msr_value);
+		
+		crc = msr_value.low;
+	}
+
+	/* DISABLE DF DIAG BUS OUTPUTS */
+
+	msr_value.low  = 0x00000000;
+	msr_value.high = 0x00000000;
+	msr_write64 (MSR_DEVICE_GEODELX_DF,  MSR_GEODELINK_DIAG, &msr_value);
+
+	/* DISABLE GLCP ACTIONS */
+
+	msr_write64 (MSR_DEVICE_GEODELX_GLCP, GLCP_DIAGCTL, &msr_value);
+
+    return crc;
+}
+
+/*---------------------------------------------------------------------------
+ * df_read_panel_crc
+ *
+ * This routine reads the CRC for a frame of data after the panel dithering
+ * logic.
+ *---------------------------------------------------------------------------*/
+
+unsigned long df_read_panel_crc (void)
+{
+	Q_WORD msr_value;
+    unsigned long timeout = 1000;
+
+	if (!(READ_REG32 (DC3_DISPLAY_CFG) & DC3_DCFG_TGEN))
+		return 0xFFFFFFFF;
+
+	/* ENABLE 32-BIT CRCS */
+
+	msr_read64 (MSR_DEVICE_GEODELX_DF, DF_MBD_MSR_DIAG_DF, &msr_value);
+	msr_value.low |= DF_DIAG_32BIT_CRC;
+	msr_write64 (MSR_DEVICE_GEODELX_DF, DF_MBD_MSR_DIAG_DF, &msr_value);
+
+	/* RESET CRC */
+
+	WRITE_VID32 (DF_PANEL_CRC, 0);
+
+    /* WAIT FOR THE RESET TO BE LATCHED */
+
+    while ((READ_VID32 (DF_PANEL_CRC32) != 0x00000001) && timeout)
+        timeout--;
+
+	WRITE_VID32 (DF_PANEL_CRC, 1);
+
+	/* WAIT FOR THE CRC TO BE COMPLETED */
+	
+    while (!(READ_VID32 (DF_PANEL_CRC) & 4))
+        ;
+
+	return READ_VID32 (DF_PANEL_CRC32);
+}
+
+/*---------------------------------------------------------------------------
+ * df_get_video_enable
+ *
+ * This routine reads the enable status of the video overlay.
+ *---------------------------------------------------------------------------*/
+
+int df_get_video_enable (int *enable, unsigned long *flags)
+{
+    *enable = 0;
+    *flags  = 0;
+	if (READ_VID32 (DF_VIDEO_CONFIG) & DF_VCFG_VID_EN)
+    {
+		*enable = 1;
+
+        /* CHECK FOR COLOR KEY DISABLED */
+        /* Color keying can be completely disabled when video is enabled to */
+        /* allow unhindered per-pixel alpha blending.  As color keying is   */
+        /* always disabled when video is disabled, it is only possible to   */
+        /* test for this condition when video is enabled.                   */
+
+        if (!(READ_VID32 (DF_DISPLAY_CONFIG) & DF_DCFG_VG_CK) &&
+            !(READ_REG32 (DC3_COLOR_KEY) & DC3_CLR_KEY_ENABLE))
+        {
+            *flags = DF_ENABLEFLAG_NOCOLORKEY;
+        }
+    }
+	
+	return CIM_STATUS_OK;
+}
+
+/*---------------------------------------------------------------------------
+ * df_get_video_source_configuration
+ *
+ * This routine reads the current configuration of the source buffers for the
+ * video overlay.
+ *---------------------------------------------------------------------------*/
+
+int df_get_video_source_configuration (DF_VIDEO_SOURCE_PARAMS *video_source_odd,
+	DF_VIDEO_SOURCE_PARAMS *video_source_even)
+{
+	unsigned long format, temp;
+	unsigned long size;
+
+	/* READ VIDEO FORMAT */
+
+	temp = READ_VID32 (DF_VIDEO_CONFIG);
+
+	format = (temp >> 2) & 3;
+	if (temp & DF_VCFG_4_2_0_MODE)
+		format |= 4;
+	else if (READ_VID32 (DF_VID_ALPHA_CONTROL) & DF_VIDEO_INPUT_IS_RGB)
+		format |= 8;
+	video_source_odd->video_format = format;
+
+	/* CHECK IF SOURCE IS HD VIDEO */
+
+	if (READ_VID32 (DF_VID_ALPHA_CONTROL) & DF_HD_VIDEO)
+		video_source_odd->flags = DF_SOURCEFLAG_HDTVSOURCE;
+	else
+		video_source_odd->flags = 0;
+
+    /* READ SCALING ALGORITHM */
+
+    if (READ_VID32 (DF_VID_MISC) & DF_USER_IMPLICIT_SCALING)
+        video_source_odd->flags |= DF_SOURCEFLAG_IMPLICITSCALING;
+
+	/* READ VIDEO PITCH */
+
+	temp = READ_REG32 (DC3_VID_YUV_PITCH);
+	video_source_odd->y_pitch  = (temp & 0xFFFF) << 3;
+	video_source_odd->uv_pitch = (temp >> 16) << 3;
+	
+	/* READ VIDEO SIZE */
+
+	temp = READ_VID32 (DF_VIDEO_CONFIG);
+	size = (temp >> 8) & 0xFF;
+	if (temp & DF_VCFG_LINE_SIZE_BIT8) size |= 0x100;
+	if (temp & DF_VCFG_LINE_SIZE_BIT9) size |= 0x200;
+
+	video_source_odd->width  = size << 1;
+	video_source_odd->height = READ_VID32 (DF_VIDEO_SCALER) & 0x7FF;
+
+	/* READ VIDEO OFFSETS */
+
+    video_source_odd->y_offset = READ_REG32 (DC3_VID_Y_ST_OFFSET) & 0xFFFFFFF;
+	video_source_odd->u_offset = READ_REG32 (DC3_VID_U_ST_OFFSET) & 0xFFFFFFF;
+	video_source_odd->v_offset = READ_REG32 (DC3_VID_V_ST_OFFSET) & 0xFFFFFFF;
+
+	if (READ_REG32 (DC3_IRQ_FILT_CTL) & DC3_IRQFILT_INTL_EN)
+	{
+		video_source_even->y_offset = READ_REG32 (DC3_VID_EVEN_Y_ST_OFFSET) & 0xFFFFFFF;
+		video_source_even->u_offset = READ_REG32 (DC3_VID_EVEN_U_ST_OFFSET) & 0xFFFFFFF;
+		video_source_even->v_offset = READ_REG32 (DC3_VID_EVEN_V_ST_OFFSET) & 0xFFFFFFF;
+	}
+	
+	return CIM_STATUS_OK;
+}
+
+/*---------------------------------------------------------------------------
+ * df_get_video_position
+ *
+ * This routine reads the current position of the video overlay.
+ *---------------------------------------------------------------------------*/
+
+int df_get_video_position (DF_VIDEO_POSITION *video_window)
+{
+    unsigned long xreg, yreg, dst_clip, clip;
+    unsigned long height;
+	unsigned long xend, yend;
+	unsigned long hsyncend, htotal;
+	unsigned long vsyncend, vtotal;
+	unsigned long hadjust, vadjust;
+    unsigned long misc, gfxscale;
+    unsigned long temp;
+	long xstart, ystart;
+	
+	video_window->flags = DF_POSFLAG_DIRECTCLIP;
+
+	hsyncend = ((READ_REG32 (DC3_H_SYNC_TIMING)   >> 16) & 0xFFF) + 1;
+	htotal   = ((READ_REG32 (DC3_H_ACTIVE_TIMING) >> 16) & 0xFFF) + 1;
+
+    /* ODD FIELD START COUNTS FROM THE EVEN FIELD TIMINGS */
+    /* We assume that the even field y position is always programmed */
+    /* to be just after the odd field.                               */
+
+    if (READ_REG32 (DC3_IRQ_FILT_CTL) & DC3_IRQFILT_INTL_EN)
+    {
+        vsyncend = ((READ_REG32 (DC3_V_SYNC_EVEN)   >> 16) & 0xFFF) + 1;
+	    vtotal   = ((READ_REG32 (DC3_V_ACTIVE_EVEN) >> 16) & 0xFFF) + 1;
+    }
+    else
+    {
+        vsyncend = ((READ_REG32 (DC3_V_SYNC_TIMING)   >> 16) & 0xFFF) + 1;
+	    vtotal   = ((READ_REG32 (DC3_V_ACTIVE_TIMING) >> 16) & 0xFFF) + 1;
+    }
+	
+	hadjust = htotal - hsyncend - 14;
+	vadjust = vtotal - vsyncend + 1;
+
+	xreg = READ_VID32 (DF_VIDEO_X_POS);
+	yreg = READ_VID32 (DF_VIDEO_Y_POS);
+
+	xstart = (xreg & 0xFFF) - hadjust;
+	ystart = (yreg & 0x7FF) - vadjust;
+	xend   = ((xreg >> 16) & 0xFFF) - hadjust;
+	yend   = ((yreg >> 16) & 0x7FF) - vadjust;
+	
+    height = yend - ystart;
+
+    if (READ_REG32 (DC3_IRQ_FILT_CTL) & DC3_IRQFILT_INTL_EN)
+    {
+        /* Y COORDINATE IS ACTUALLY 2X THE ODD FIELD START */
+
+        ystart <<= 1;
+
+        /* CALCULATE THE EXACT VIDEO HEIGHT */
+        /* The height of the video window is the sum of the */
+        /* odd and even field heights.                      */
+
+        yreg = READ_VID32 (DF_VID_YPOS_EVEN);
+        height += ((yreg >> 16) & 0x7FF) - (yreg & 0x7FF);
+    }
+
+	clip = ((READ_VID32 (DF_VIDEO_CONFIG) >> 16) & 0x1FF) << 2;
+
+	/* ADJUST FOR CLIPPING VALUES THAT ARE NOT FOUR-PIXEL ALIGNED */
+
+    dst_clip = 0;
+	if (xstart < 0)
+	{
+		dst_clip += -xstart;
+		xstart = 0;
+	}
+
+    /* REVERSE THE GRAPHICS SCALE */
+
+    misc = READ_VID32 (DF_VID_MISC);
+    if (misc & DF_USER_IMPLICIT_SCALING)
+    {
+        gfxscale = READ_REG32 (DC3_GFX_SCALE);
+
+        if (gfxscale != 0x40004000)
+        {
+            temp = ystart + height;
+            temp = (temp * (gfxscale >> 16)) / 0x4000;
+
+            xstart = (xstart * (gfxscale & 0xFFFF)) / 0x4000;
+            xend   = (xend   * (gfxscale & 0xFFFF)) / 0x4000;
+            ystart = (ystart * (gfxscale >> 16)) / 0x4000;
+            height = temp - ystart;
+        }
+    }
+
+	video_window->left_clip = clip;
+    video_window->dst_clip  = dst_clip;
+	video_window->x         = xstart;
+	video_window->y         = ystart;
+	video_window->width     = xend - xstart;
+	video_window->height    = height;
+
+	return CIM_STATUS_OK;
+}
+
+/*---------------------------------------------------------------------------
+ * df_get_video_scale
+ *
+ * This routine reads the current scale values for video scaling.
+ *---------------------------------------------------------------------------*/
+
+int df_get_video_scale (unsigned long *x_scale, unsigned long *y_scale)
+{
+	*x_scale = READ_VID32 (DF_VIDEO_XSCALE) & 0x000FFFFF;
+	*y_scale = READ_VID32 (DF_VIDEO_YSCALE) & 0x000FFFFF;
+	return CIM_STATUS_OK;
+}
+
+/*---------------------------------------------------------------------------
+ * df_get_video_filter_coefficients
+ *
+ * This routine reads the coefficients for the video scaler/filter.
+ *---------------------------------------------------------------------------*/
+
+int df_get_video_filter_coefficients (long taps[][4], int *phase256)
+{
+	unsigned long i, temp;
+	long coeff;
+
+	if (READ_VID32 (DF_VIDEO_SCALER) & DF_SCALE_128_PHASES)
+		*phase256 = 0;
+	else
+		*phase256 = 1;
+
+	for (i = 0; i < 256; i++)
+	{
+		temp = READ_VID32 (DF_COEFFICIENT_BASE + (i << 3));
+
+		/* TAP 0 */
+
+		coeff = temp & 0x7FFF;
+		if (temp & 0x8000) coeff = -coeff;
+		taps[i][0] = coeff;
+
+		/* TAP 1 */
+
+		temp >>= 16;
+		coeff = temp & 0x7FFF;
+		if (temp & 0x8000) coeff = -coeff;
+		taps[i][1] = coeff;
+
+		temp = READ_VID32 (DF_COEFFICIENT_BASE + (i << 3) + 4);
+
+		/* TAP 2 */
+
+		coeff = temp & 0x7FFF;
+		if (temp & 0x8000) coeff = -coeff;
+		taps[i][2] = coeff;
+
+		/* TAP 3 */
+
+		temp >>= 16;
+		coeff = temp & 0x7FFF;
+		if (temp & 0x8000) coeff = -coeff;
+		taps[i][3] = coeff;
+	}
+
+	return CIM_STATUS_OK;
+}
+
+/*---------------------------------------------------------------------------
+ * df_get_video_color_key
+ *
+ * This routine reads the current settings for hardware color/chroma keying.
+ *---------------------------------------------------------------------------*/
+
+int df_get_video_color_key (unsigned long *key, unsigned long *mask, int *graphics)
+{
+	unsigned long chroma = READ_VID32 (DF_DISPLAY_CONFIG) & DF_DCFG_VG_CK;
+
+	if (chroma)
+	{
+		/* CHROMA KEY - READ KEY AND MASK FROM DF */
+
+		*graphics = 0;
+		*key  = READ_VID32 (DF_VIDEO_COLOR_KEY) & 0xFFFFFF;
+		*mask = READ_VID32 (DF_VIDEO_COLOR_MASK) & 0xFFFFFF;
+	}
+	else
+	{
+		*graphics = 1;
+
+		*key  = READ_REG32 (DC3_COLOR_KEY) & 0xFFFFFF;
+        *mask = READ_REG32 (DC3_COLOR_MASK) & 0xFFFFFF;
+	}
+	
+	return CIM_STATUS_OK;
+}
+
+/*---------------------------------------------------------------------------
+ * df_get_video_palette_entry
+ *
+ * This routine returns a single palette entry.
+ *---------------------------------------------------------------------------*/
+
+int df_get_video_palette_entry(unsigned long index, unsigned long *palette)
+{
+	if (index > 0xFF)
+		return CIM_STATUS_INVALIDPARAMS;
+
+	/* READ A SINGLE ENTRY */
+
+	WRITE_VID32 (DF_PALETTE_ADDRESS, index);
+	*palette = READ_VID32 (DF_PALETTE_DATA);
+
+	return CIM_STATUS_OK;
+}
+
+/*---------------------------------------------------------------------------
+ * df_get_video_palette
+ *
+ * This routine returns the entire video palette.
+ *---------------------------------------------------------------------------*/
+
+int df_get_video_palette (unsigned long *palette)
+{
+    unsigned long i;
+
+	WRITE_VID32 (DF_PALETTE_ADDRESS, 0);
+	for (i = 0; i < 256; i++)
+        palette[i] = READ_VID32 (DF_PALETTE_DATA);
+
+	return CIM_STATUS_OK;
+}
+
+/*---------------------------------------------------------------------------
+ * df_get_video_cursor_color_key
+ *
+ * This routine returns the current configuration for the hardware video cursor
+ * color key.
+ *---------------------------------------------------------------------------*/
+
+int df_get_video_cursor_color_key (DF_VIDEO_CURSOR_PARAMS *cursor_color_key)
+{
+	unsigned long key;
+
+	cursor_color_key->flags  = 0;
+	cursor_color_key->color1 = READ_VID32 (DF_CURSOR_COLOR_1) & 0xFFFFFF;
+	cursor_color_key->color2 = READ_VID32 (DF_CURSOR_COLOR_2) & 0xFFFFFF;
+	cursor_color_key->mask   = READ_VID32 (DF_CURSOR_COLOR_MASK) & 0xFFFFFF;
+
+	key = READ_VID32 (DF_CURSOR_COLOR_KEY);
+	cursor_color_key->key = key & 0xFFFFFF;
+	cursor_color_key->select_color2 = (key >> 24) & 0x1F;
+
+	return CIM_STATUS_OK;
+}
+
+/*---------------------------------------------------------------------------
+ * df_get_video_cursor_color_key_enable
+ *
+ * This routine returns the current enable status of the hardware video cursor
+ * color key.
+ *---------------------------------------------------------------------------*/
+
+int df_get_video_cursor_color_key_enable (void)
+{
+	if (READ_VID32 (DF_CURSOR_COLOR_KEY) & DF_CURSOR_COLOR_KEY_ENABLE)
+		return 1;
+
+	return 0;
+}
+
+/*---------------------------------------------------------------------------
+ * df_get_alpha_window_configuration
+ *
+ * This routine reads the current configuration for one of the three hardware
+ * alpha regions.
+ *---------------------------------------------------------------------------*/
+
+int df_get_alpha_window_configuration (int window, DF_ALPHA_REGION_PARAMS *alpha_data)
+{
+	unsigned long pos, color, alpha_ctl;
+	unsigned long hsyncend, htotal;
+	unsigned long vsyncend, vtotal;
+	unsigned long hadjust, vadjust;
+	unsigned long xreg, yreg;
+    unsigned long misc, gfxscale;
+    unsigned long temp;
+	char delta;
+	
+	if (window > 2)
+		return CIM_STATUS_INVALIDPARAMS;
+
+	hsyncend = ((READ_REG32 (DC3_H_SYNC_TIMING)   >> 16) & 0xFFF) + 1;
+	htotal   = ((READ_REG32 (DC3_H_ACTIVE_TIMING) >> 16) & 0xFFF) + 1;
+    if (READ_REG32 (DC3_IRQ_FILT_CTL) & DC3_IRQFILT_INTL_EN)
+    {
+	    vtotal   = ((READ_REG32 (DC3_V_ACTIVE_EVEN) >> 16) & 0xFFF) + 1;
+        vsyncend = ((READ_REG32 (DC3_V_SYNC_EVEN)   >> 16) & 0xFFF) + 1;
+    }
+    else
+    {
+        vtotal   = ((READ_REG32 (DC3_V_ACTIVE_TIMING) >> 16) & 0xFFF) + 1;
+        vsyncend = ((READ_REG32 (DC3_V_SYNC_TIMING)   >> 16) & 0xFFF) + 1;
+    }
+
+	/* GET PRIORITY */
+
+	pos = 16 + (window << 1);
+	alpha_data->priority = (READ_VID32 (DF_VID_ALPHA_CONTROL) >> pos) & 3L;
+	
+	/* GET ALPHA WINDOW */
+
+	hadjust = htotal - hsyncend - 2;
+	vadjust = vtotal - vsyncend + 1;
+
+	xreg = READ_VID32 (DF_ALPHA_XPOS_1 + (window << 5));
+	yreg = READ_VID32 (DF_ALPHA_YPOS_1 + (window << 5));
+	alpha_data->width  = ((xreg >> 16) & 0xFFF) - (xreg & 0xFFF);
+	alpha_data->height = ((yreg >> 16) & 0x7FF) - (yreg & 0x7FF);
+	alpha_data->x = (xreg & 0xFFF) - hadjust;
+	alpha_data->y = (yreg & 0x7FF) - vadjust;
+
+    /* REVERSE THE GRAPHICS SCALE */
+
+    misc = READ_VID32 (DF_VID_MISC);
+    if (misc & DF_USER_IMPLICIT_SCALING)
+    {
+        gfxscale = READ_REG32 (DC3_GFX_SCALE);
+        if (gfxscale != 0x40004000)
+        {
+            temp = alpha_data->y + alpha_data->height;
+            temp = (temp * (gfxscale >> 16)) / 0x4000;
+
+            alpha_data->x      = (alpha_data->x * (gfxscale & 0xFFFF)) / 0x4000;
+            alpha_data->width  = (alpha_data->width * (gfxscale & 0xFFFF)) / 0x4000;
+            alpha_data->y      = (alpha_data->y * (gfxscale >> 16)) / 0x4000;
+            alpha_data->height = temp - alpha_data->y;
+        }
+    }
+
+    if (READ_REG32 (DC3_IRQ_FILT_CTL) & DC3_IRQFILT_INTL_EN)
+    {
+        /* Y COORDINATE IS ACTUALLY 2X THE ODD FIELD START */
+
+        alpha_data->y <<= 1;
+
+        /* CALCULATE THE EXACT VIDEO HEIGHT */
+        /* The height of the video window is the sum of the */
+        /* odd and even field heights.                      */
+
+        yreg = READ_VID32 (DF_VID_ALPHA_Y_EVEN_1 + (window << 3));
+        alpha_data->height += ((yreg >> 16) & 0x7FF) - (yreg & 0x7FF);
+    }
+
+	/* GET COLOR REGISTER */
+
+	color = READ_VID32 (DF_ALPHA_COLOR_1 + (window << 5));
+	alpha_data->color = color & 0xFFFFFF;
+	if (color & DF_ALPHA_COLOR_ENABLE)
+		alpha_data->flags = DF_ALPHAFLAG_COLORENABLED;
+	else
+		alpha_data->flags = 0;
+
+	/* GET ALPHA VALUE, DELTA AND PER PIXEL */
+
+	alpha_ctl = READ_VID32 (DF_ALPHA_CONTROL_1 + (window << 5));
+	alpha_data->alpha_value = alpha_ctl & 0xFF;
+	if (alpha_ctl & DF_ACTRL_PERPIXEL_EN)
+		alpha_data->flags |= DF_ALPHAFLAG_PERPIXELENABLED;
+
+	delta = (char)((alpha_ctl >> 8) & 0xFF);
+	alpha_data->delta = (long)delta;
+	return CIM_STATUS_OK;
+}
+
+/*---------------------------------------------------------------------------
+ * df_get_alpha_window_enable
+ *
+ * This routine reads the current enable status of one of the three hardware
+ * alpha regions.
+ *---------------------------------------------------------------------------*/
+
+int df_get_alpha_window_enable (int window)
+{
+	if (window > 2)
+		return 0;
+
+	if (READ_VID32 (DF_ALPHA_CONTROL_1 + (window << 5)) & DF_ACTRL_WIN_ENABLE)
+		return 1;
+
+	return 0;
+}
+
+/*---------------------------------------------------------------------------
+ * df_get_video_request
+ *
+ * This routine reads the horizontal (pixel) and vertical (line) video request
+ * values.
+ *--------------------------------------------------------------------------*/
+
+int df_get_video_request (unsigned long *x, unsigned long *y)
+{	
+	unsigned long request;
+	unsigned long hsyncend, htotal;
+	unsigned long vsyncend, vtotal;
+
+	hsyncend = ((READ_REG32 (DC3_H_SYNC_TIMING)   >> 16) & 0xFFF) + 1;
+	vsyncend = ((READ_REG32 (DC3_V_SYNC_TIMING)   >> 16) & 0xFFF) + 1;
+	htotal   = ((READ_REG32 (DC3_H_ACTIVE_TIMING) >> 16) & 0xFFF) + 1;
+	vtotal   = ((READ_REG32 (DC3_V_ACTIVE_TIMING) >> 16) & 0xFFF) + 1;
+
+	request = READ_VID32 (DF_VIDEO_REQUEST);
+	*x = ((request >> 16) & 0xFFF) - (htotal - hsyncend - 2);
+	*y =  (request & 0x7FF) - (vtotal - vsyncend + 1);
+
+	return CIM_STATUS_OK;
+}
+
+/*---------------------------------------------------------------------------
+ * df_get_output_color_space
+ *
+ * This routine sets the color space used when combining graphics and video.
+ *--------------------------------------------------------------------------*/
+
+int df_get_output_color_space (int *color_space)
+{	
+	unsigned long alpha_ctl;
+
+	alpha_ctl = READ_VID32 (DF_VID_ALPHA_CONTROL);
+
+    if ((alpha_ctl & DF_CSC_VIDEO_YUV_TO_RGB) ||
+       !(alpha_ctl & DF_CSC_GRAPHICS_RGB_TO_YUV))
+    {
+        if (alpha_ctl & DF_ALPHA_DRGB)
+            *color_space = DF_OUTPUT_ARGB;
+        else
+            *color_space = DF_OUTPUT_RGB;
+    }
+    else
+    {
+        *color_space = DF_OUTPUT_SDTV;
+
+        if (alpha_ctl & DF_HD_GRAPHICS)
+            *color_space = DF_OUTPUT_HDTV;
+    }
+
+    return CIM_STATUS_OK;
+}
+
+#endif
diff --git a/lib/cimarron/cim/cim_filter.c b/lib/cimarron/cim/cim_filter.c
new file mode 100644
index 0000000..60f424e
--- /dev/null
+++ b/lib/cimarron/cim/cim_filter.c
@@ -0,0 +1,533 @@
+ /*
+  * <LIC_AMD_STD>
+  * Copyright (C) 2005 Advanced Micro Devices, Inc.  All Rights Reserved.
+  * </LIC_AMD_STD>
+  *
+  * <CTL_AMD_STD>
+  * </CTL_AMD_STD>
+  *
+  * <DOC_AMD_STD>
+  * Cimarron default video coefficients.
+  * </DOC_AMD_STD>
+  *
+  */
+
+long CimarronVideoFilter256[][2] =
+{
+	{ 0x10000000, 0x00000000 },  /*     0, 4096,    0,    0 */
+    { 0x10008008, 0x00000008 },  /*    -8, 4096,    8,    0 */
+    { 0x10008010, 0x80010011 },  /*   -16, 4096,   17,   -1 */
+    { 0x10008019, 0x8001001A },  /*   -25, 4096,   26,   -1 */
+    { 0x10008021, 0x80020023 },  /*   -33, 4096,   35,   -2 */
+    { 0x0FFF8029, 0x8003002D },  /*   -41, 4095,   45,   -3 */
+    { 0x0FFE8031, 0x80030036 },  /*   -49, 4094,   54,   -3 */
+    { 0x0FFC8038, 0x80040040 },  /*   -56, 4092,   64,   -4 */
+    { 0x0FFB8040, 0x8005004A },  /*   -64, 4091,   74,   -5 */
+    { 0x0FF88047, 0x80050054 },  /*   -71, 4088,   84,   -5 */
+    { 0x0FF6804E, 0x8006005E },  /*   -78, 4086,   94,   -6 */
+    { 0x0FF48055, 0x80070068 },  /*   -85, 4084,  104,   -7 */
+    { 0x0FF0805C, 0x80070073 },  /*   -92, 4080,  115,   -7 */
+    { 0x0FEE8063, 0x8008007D },  /*   -99, 4078,  125,   -8 */
+    { 0x0FEA8069, 0x80090088 },  /*  -105, 4074,  136,   -9 */
+    { 0x0FE78070, 0x800A0093 },  /*  -112, 4071,  147,  -10 */
+    { 0x0FE28076, 0x800A009E },  /*  -118, 4066,  158,  -10 */
+    { 0x0FDD807C, 0x800B00AA },  /*  -124, 4061,  170,  -11 */
+    { 0x0FD98082, 0x800C00B5 },  /*  -130, 4057,  181,  -12 */
+    { 0x0FD48088, 0x800D00C1 },  /*  -136, 4052,  193,  -13 */
+    { 0x0FCE808E, 0x800D00CD },  /*  -142, 4046,  205,  -13 */
+    { 0x0FC88093, 0x800E00D9 },  /*  -147, 4040,  217,  -14 */
+    { 0x0FC38099, 0x800F00E5 },  /*  -153, 4035,  229,  -15 */
+    { 0x0FBD809E, 0x801000F1 },  /*  -158, 4029,  241,  -16 */
+    { 0x0FB680A3, 0x801000FD },  /*  -163, 4022,  253,  -16 */
+    { 0x0FAF80A8, 0x8011010A },  /*  -168, 4015,  266,  -17 */
+    { 0x0FA880AD, 0x80120117 },  /*  -173, 4008,  279,  -18 */
+    { 0x0FA180B2, 0x80130124 },  /*  -178, 4001,  292,  -19 */
+    { 0x0F9980B6, 0x80140131 },  /*  -182, 3993,  305,  -20 */
+    { 0x0F9280BB, 0x8015013E },  /*  -187, 3986,  318,  -21 */
+    { 0x0F8880BF, 0x8015014C },  /*  -191, 3976,  332,  -21 */
+    { 0x0F8080C3, 0x80160159 },  /*  -195, 3968,  345,  -22 */
+    { 0x0F7880C8, 0x80170167 },  /*  -200, 3960,  359,  -23 */
+    { 0x0F6E80CB, 0x80180175 },  /*  -203, 3950,  373,  -24 */
+    { 0x0F6580CF, 0x80190183 },  /*  -207, 3941,  387,  -25 */
+    { 0x0F5C80D3, 0x801A0191 },  /*  -211, 3932,  401,  -26 */
+    { 0x0F5280D7, 0x801B01A0 },  /*  -215, 3922,  416,  -27 */
+    { 0x0F4880DA, 0x801C01AE },  /*  -218, 3912,  430,  -28 */
+    { 0x0F3D80DD, 0x801D01BD },  /*  -221, 3901,  445,  -29 */
+    { 0x0F3280E0, 0x801E01CC },  /*  -224, 3890,  460,  -30 */
+    { 0x0F2880E4, 0x801F01DB },  /*  -228, 3880,  475,  -31 */
+    { 0x0F1C80E6, 0x802001EA },  /*  -230, 3868,  490,  -32 */
+    { 0x0F1180E9, 0x802101F9 },  /*  -233, 3857,  505,  -33 */
+    { 0x0F0480EB, 0x80210208 },  /*  -235, 3844,  520,  -33 */
+    { 0x0EFA80EF, 0x80230218 },  /*  -239, 3834,  536,  -35 */
+    { 0x0EEC80F0, 0x80230227 },  /*  -240, 3820,  551,  -35 */
+    { 0x0EE080F3, 0x80240237 },  /*  -243, 3808,  567,  -36 */
+    { 0x0ED380F5, 0x80250247 },  /*  -245, 3795,  583,  -37 */
+    { 0x0EC780F7, 0x80270257 },  /*  -247, 3783,  599,  -39 */
+    { 0x0EB980F9, 0x80280268 },  /*  -249, 3769,  616,  -40 */
+    { 0x0EAC80FB, 0x80290278 },  /*  -251, 3756,  632,  -41 */
+    { 0x0E9E80FD, 0x802A0289 },  /*  -253, 3742,  649,  -42 */
+    { 0x0E9080FE, 0x802B0299 },  /*  -254, 3728,  665,  -43 */
+    { 0x0E838100, 0x802D02AA },  /*  -256, 3715,  682,  -45 */
+    { 0x0E758102, 0x802E02BB },  /*  -258, 3701,  699,  -46 */
+    { 0x0E668103, 0x802F02CC },  /*  -259, 3686,  716,  -47 */
+    { 0x0E568104, 0x803002DE },  /*  -260, 3670,  734,  -48 */
+    { 0x0E498106, 0x803202EF },  /*  -262, 3657,  751,  -50 */
+    { 0x0E398107, 0x80330301 },  /*  -263, 3641,  769,  -51 */
+    { 0x0E298108, 0x80340313 },  /*  -264, 3625,  787,  -52 */
+    { 0x0E1A8109, 0x80360325 },  /*  -265, 3610,  805,  -54 */
+    { 0x0E0B810A, 0x80370336 },  /*  -266, 3595,  822,  -55 */
+    { 0x0DFA810A, 0x80380348 },  /*  -266, 3578,  840,  -56 */
+    { 0x0DEA810B, 0x803A035B },  /*  -267, 3562,  859,  -58 */
+    { 0x0DDA810C, 0x803B036D },  /*  -268, 3546,  877,  -59 */
+    { 0x0DCA810C, 0x803D037F },  /*  -268, 3530,  895,  -61 */
+    { 0x0DB7810B, 0x803E0392 },  /*  -267, 3511,  914,  -62 */
+    { 0x0DA7810C, 0x804003A5 },  /*  -268, 3495,  933,  -64 */
+    { 0x0D95810C, 0x804103B8 },  /*  -268, 3477,  952,  -65 */
+    { 0x0D85810C, 0x804303CA },  /*  -268, 3461,  970,  -67 */
+    { 0x0D73810C, 0x804403DD },  /*  -268, 3443,  989,  -68 */
+    { 0x0D61810C, 0x804603F1 },  /*  -268, 3425, 1009,  -70 */
+    { 0x0D50810C, 0x80480404 },  /*  -268, 3408, 1028,  -72 */
+    { 0x0D3E810C, 0x80490417 },  /*  -268, 3390, 1047,  -73 */
+    { 0x0D2C810C, 0x804B042B },  /*  -268, 3372, 1067,  -75 */
+    { 0x0D1B810C, 0x804D043E },  /*  -268, 3355, 1086,  -77 */
+    { 0x0D07810B, 0x804E0452 },  /*  -267, 3335, 1106,  -78 */
+    { 0x0CF5810B, 0x80500466 },  /*  -267, 3317, 1126,  -80 */
+    { 0x0CE2810A, 0x8052047A },  /*  -266, 3298, 1146,  -82 */
+    { 0x0CCF810A, 0x8053048E },  /*  -266, 3279, 1166,  -83 */
+    { 0x0CBC8109, 0x805504A2 },  /*  -265, 3260, 1186,  -85 */
+    { 0x0CA98108, 0x805704B6 },  /*  -264, 3241, 1206,  -87 */
+    { 0x0C968108, 0x805904CB },  /*  -264, 3222, 1227,  -89 */
+    { 0x0C838107, 0x805B04DF },  /*  -263, 3203, 1247,  -91 */
+    { 0x0C6F8106, 0x805C04F3 },  /*  -262, 3183, 1267,  -92 */
+    { 0x0C5B8105, 0x805E0508 },  /*  -261, 3163, 1288,  -94 */
+    { 0x0C478104, 0x8060051D },  /*  -260, 3143, 1309,  -96 */
+    { 0x0C348103, 0x80620531 },  /*  -259, 3124, 1329,  -98 */
+    { 0x0C1F8102, 0x80640547 },  /*  -258, 3103, 1351, -100 */
+    { 0x0C0C8101, 0x8066055B },  /*  -257, 3084, 1371, -102 */
+    { 0x0BF88100, 0x80680570 },  /*  -256, 3064, 1392, -104 */
+    { 0x0BE380FE, 0x806A0585 },  /*  -254, 3043, 1413, -106 */
+    { 0x0BCF80FD, 0x806C059A },  /*  -253, 3023, 1434, -108 */
+    { 0x0BBA80FC, 0x806E05B0 },  /*  -252, 3002, 1456, -110 */
+    { 0x0BA480F9, 0x807005C5 },  /*  -249, 2980, 1477, -112 */
+    { 0x0B8F80F8, 0x807205DB },  /*  -248, 2959, 1499, -114 */
+    { 0x0B7A80F6, 0x807405F0 },  /*  -246, 2938, 1520, -116 */
+    { 0x0B6580F5, 0x80760606 },  /*  -245, 2917, 1542, -118 */
+    { 0x0B4F80F3, 0x8077061B },  /*  -243, 2895, 1563, -119 */
+    { 0x0B3A80F2, 0x80790631 },  /*  -242, 2874, 1585, -121 */
+    { 0x0B2480F0, 0x807B0647 },  /*  -240, 2852, 1607, -123 */
+    { 0x0B0F80EE, 0x807D065C },  /*  -238, 2831, 1628, -125 */
+    { 0x0AF980ED, 0x807F0673 },  /*  -237, 2809, 1651, -127 */
+    { 0x0AE480EB, 0x80810688 },  /*  -235, 2788, 1672, -129 */
+    { 0x0ACE80E9, 0x8084069F },  /*  -233, 2766, 1695, -132 */
+    { 0x0AB980E7, 0x808606B4 },  /*  -231, 2745, 1716, -134 */
+    { 0x0AA380E6, 0x808806CB },  /*  -230, 2723, 1739, -136 */
+    { 0x0A8D80E4, 0x808A06E1 },  /*  -228, 2701, 1761, -138 */
+    { 0x0A7780E2, 0x808C06F7 },  /*  -226, 2679, 1783, -140 */
+    { 0x0A6180E0, 0x808E070D },  /*  -224, 2657, 1805, -142 */
+    { 0x0A4B80DE, 0x80910724 },  /*  -222, 2635, 1828, -145 */
+    { 0x0A3580DC, 0x8093073A },  /*  -220, 2613, 1850, -147 */
+    { 0x0A1F80DA, 0x80950750 },  /*  -218, 2591, 1872, -149 */
+    { 0x0A0880D8, 0x80970767 },  /*  -216, 2568, 1895, -151 */
+    { 0x09F280D6, 0x8099077D },  /*  -214, 2546, 1917, -153 */
+    { 0x09DD80D4, 0x809C0793 },  /*  -212, 2525, 1939, -156 */
+    { 0x09C680D2, 0x809E07AA },  /*  -210, 2502, 1962, -158 */
+    { 0x09B080D0, 0x80A007C0 },  /*  -208, 2480, 1984, -160 */
+    { 0x099980CE, 0x80A207D7 },  /*  -206, 2457, 2007, -162 */
+    { 0x098380CB, 0x80A507ED },  /*  -203, 2435, 2029, -165 */
+    { 0x096C80C9, 0x80A70804 },  /*  -201, 2412, 2052, -167 */
+    { 0x095680C7, 0x80A9081A },  /*  -199, 2390, 2074, -169 */
+    { 0x094080C5, 0x80AB0830 },  /*  -197, 2368, 2096, -171 */
+    { 0x092980C3, 0x80AE0848 },  /*  -195, 2345, 2120, -174 */
+    { 0x091380C1, 0x80B0085E },  /*  -193, 2323, 2142, -176 */
+    { 0x08FC80BE, 0x80B20874 },  /*  -190, 2300, 2164, -178 */
+    { 0x08E580BC, 0x80B4088B },  /*  -188, 2277, 2187, -180 */
+    { 0x08D080BB, 0x80B708A2 },  /*  -187, 2256, 2210, -183 */
+    { 0x08B980B9, 0x80B908B9 },  /*  -185, 2233, 2233, -185 */
+    { 0x08A380B7, 0x80BB08CF },  /*  -183, 2211, 2255, -187 */
+    { 0x088B80B4, 0x80BC08E5 },  /*  -180, 2187, 2277, -188 */
+    { 0x087480B2, 0x80BE08FC },  /*  -178, 2164, 2300, -190 */
+    { 0x085E80B0, 0x80C10913 },  /*  -176, 2142, 2323, -193 */
+    { 0x084880AE, 0x80C30929 },  /*  -174, 2120, 2345, -195 */
+    { 0x083080AB, 0x80C50940 },  /*  -171, 2096, 2368, -197 */
+    { 0x081A80A9, 0x80C70956 },  /*  -169, 2074, 2390, -199 */
+    { 0x080480A7, 0x80C9096C },  /*  -167, 2052, 2412, -201 */
+    { 0x07ED80A5, 0x80CB0983 },  /*  -165, 2029, 2435, -203 */
+    { 0x07D780A2, 0x80CE0999 },  /*  -162, 2007, 2457, -206 */
+    { 0x07C080A0, 0x80D009B0 },  /*  -160, 1984, 2480, -208 */
+    { 0x07AA809E, 0x80D209C6 },  /*  -158, 1962, 2502, -210 */
+    { 0x0793809C, 0x80D409DD },  /*  -156, 1939, 2525, -212 */
+    { 0x077D8099, 0x80D609F2 },  /*  -153, 1917, 2546, -214 */
+    { 0x07668097, 0x80D80A09 },  /*  -151, 1894, 2569, -216 */
+    { 0x074F8095, 0x80DA0A20 },  /*  -149, 1871, 2592, -218 */
+    { 0x073A8093, 0x80DC0A35 },  /*  -147, 1850, 2613, -220 */
+    { 0x07238091, 0x80DE0A4C },  /*  -145, 1827, 2636, -222 */
+    { 0x070C808E, 0x80E00A62 },  /*  -142, 1804, 2658, -224 */
+    { 0x06F7808C, 0x80E20A77 },  /*  -140, 1783, 2679, -226 */
+    { 0x06E0808A, 0x80E40A8E },  /*  -138, 1760, 2702, -228 */
+    { 0x06CA8088, 0x80E60AA4 },  /*  -136, 1738, 2724, -230 */
+    { 0x06B48086, 0x80E70AB9 },  /*  -134, 1716, 2745, -231 */
+    { 0x069E8084, 0x80E90ACF },  /*  -132, 1694, 2767, -233 */
+    { 0x06878081, 0x80EB0AE5 },  /*  -129, 1671, 2789, -235 */
+    { 0x0672807F, 0x80ED0AFA },  /*  -127, 1650, 2810, -237 */
+    { 0x065C807D, 0x80EE0B0F },  /*  -125, 1628, 2831, -238 */
+    { 0x0646807B, 0x80F00B25 },  /*  -123, 1606, 2853, -240 */
+    { 0x06308079, 0x80F20B3B },  /*  -121, 1584, 2875, -242 */
+    { 0x061A8077, 0x80F30B50 },  /*  -119, 1562, 2896, -243 */
+    { 0x06068076, 0x80F50B65 },  /*  -118, 1542, 2917, -245 */
+    { 0x05F08074, 0x80F60B7A },  /*  -116, 1520, 2938, -246 */
+    { 0x05DB8072, 0x80F80B8F },  /*  -114, 1499, 2959, -248 */
+    { 0x05C58070, 0x80F90BA4 },  /*  -112, 1477, 2980, -249 */
+    { 0x05B1806E, 0x80FC0BB9 },  /*  -110, 1457, 3001, -252 */
+    { 0x059B806C, 0x80FD0BCE },  /*  -108, 1435, 3022, -253 */
+    { 0x0586806A, 0x80FE0BE2 },  /*  -106, 1414, 3042, -254 */
+    { 0x05718068, 0x81000BF7 },  /*  -104, 1393, 3063, -256 */
+    { 0x055C8066, 0x81010C0B },  /*  -102, 1372, 3083, -257 */
+    { 0x05478064, 0x81020C1F },  /*  -100, 1351, 3103, -258 */
+    { 0x05328062, 0x81030C33 },  /*   -98, 1330, 3123, -259 */
+    { 0x051D8060, 0x81040C47 },  /*   -96, 1309, 3143, -260 */
+    { 0x0508805E, 0x81050C5B },  /*   -94, 1288, 3163, -261 */
+    { 0x04F3805C, 0x81060C6F },  /*   -92, 1267, 3183, -262 */
+    { 0x04E0805B, 0x81070C82 },  /*   -91, 1248, 3202, -263 */
+    { 0x04CB8059, 0x81080C96 },  /*   -89, 1227, 3222, -264 */
+    { 0x04B68057, 0x81080CA9 },  /*   -87, 1206, 3241, -264 */
+    { 0x04A28055, 0x81090CBC },  /*   -85, 1186, 3260, -265 */
+    { 0x048E8053, 0x810A0CCF },  /*   -83, 1166, 3279, -266 */
+    { 0x047A8052, 0x810A0CE2 },  /*   -82, 1146, 3298, -266 */
+    { 0x04668050, 0x810B0CF5 },  /*   -80, 1126, 3317, -267 */
+    { 0x0451804E, 0x810B0D08 },  /*   -78, 1105, 3336, -267 */
+    { 0x043E804D, 0x810C0D1B },  /*   -77, 1086, 3355, -268 */
+    { 0x042B804B, 0x810C0D2C },  /*   -75, 1067, 3372, -268 */
+    { 0x04178049, 0x810C0D3E },  /*   -73, 1047, 3390, -268 */
+    { 0x04038048, 0x810C0D51 },  /*   -72, 1027, 3409, -268 */
+    { 0x03F08046, 0x810C0D62 },  /*   -70, 1008, 3426, -268 */
+    { 0x03DD8044, 0x810C0D73 },  /*   -68,  989, 3443, -268 */
+    { 0x03CA8043, 0x810C0D85 },  /*   -67,  970, 3461, -268 */
+    { 0x03B78041, 0x810C0D96 },  /*   -65,  951, 3478, -268 */
+    { 0x03A48040, 0x810C0DA8 },  /*   -64,  932, 3496, -268 */
+    { 0x0391803E, 0x810B0DB8 },  /*   -62,  913, 3512, -267 */
+    { 0x0380803D, 0x810C0DC9 },  /*   -61,  896, 3529, -268 */
+    { 0x036D803B, 0x810C0DDA },  /*   -59,  877, 3546, -268 */
+    { 0x035B803A, 0x810B0DEA },  /*   -58,  859, 3562, -267 */
+    { 0x03488038, 0x810A0DFA },  /*   -56,  840, 3578, -266 */
+    { 0x03368037, 0x810A0E0B },  /*   -55,  822, 3595, -266 */
+    { 0x03248036, 0x81090E1B },  /*   -54,  804, 3611, -265 */
+    { 0x03128034, 0x81080E2A },  /*   -52,  786, 3626, -264 */
+    { 0x03018033, 0x81070E39 },  /*   -51,  769, 3641, -263 */
+    { 0x02EF8032, 0x81060E49 },  /*   -50,  751, 3657, -262 */
+    { 0x02DE8030, 0x81040E56 },  /*   -48,  734, 3670, -260 */
+    { 0x02CC802F, 0x81030E66 },  /*   -47,  716, 3686, -259 */
+    { 0x02BB802E, 0x81020E75 },  /*   -46,  699, 3701, -258 */
+    { 0x02AA802D, 0x81000E83 },  /*   -45,  682, 3715, -256 */
+    { 0x0299802B, 0x80FE0E90 },  /*   -43,  665, 3728, -254 */
+    { 0x0288802A, 0x80FD0E9F },  /*   -42,  648, 3743, -253 */
+    { 0x02778029, 0x80FB0EAD },  /*   -41,  631, 3757, -251 */
+    { 0x02678028, 0x80F90EBA },  /*   -40,  615, 3770, -249 */
+    { 0x02568027, 0x80F70EC8 },  /*   -39,  598, 3784, -247 */
+    { 0x02468025, 0x80F50ED4 },  /*   -37,  582, 3796, -245 */
+    { 0x02368024, 0x80F30EE1 },  /*   -36,  566, 3809, -243 */
+    { 0x02268023, 0x80F00EED },  /*   -35,  550, 3821, -240 */
+    { 0x02188023, 0x80EF0EFA },  /*   -35,  536, 3834, -239 */
+    { 0x02078021, 0x80EB0F05 },  /*   -33,  519, 3845, -235 */
+    { 0x01F98021, 0x80E90F11 },  /*   -33,  505, 3857, -233 */
+    { 0x01EA8020, 0x80E60F1C },  /*   -32,  490, 3868, -230 */
+    { 0x01DC801F, 0x80E40F27 },  /*   -31,  476, 3879, -228 */
+    { 0x01CD801E, 0x80E00F31 },  /*   -30,  461, 3889, -224 */
+    { 0x01BE801D, 0x80DD0F3C },  /*   -29,  446, 3900, -221 */
+    { 0x01AF801C, 0x80DA0F47 },  /*   -28,  431, 3911, -218 */
+    { 0x01A1801B, 0x80D70F51 },  /*   -27,  417, 3921, -215 */
+    { 0x0192801A, 0x80D30F5B },  /*   -26,  402, 3931, -211 */
+    { 0x01848019, 0x80CF0F64 },  /*   -25,  388, 3940, -207 */
+    { 0x01768018, 0x80CB0F6D },  /*   -24,  374, 3949, -203 */
+    { 0x01688017, 0x80C80F77 },  /*   -23,  360, 3959, -200 */
+    { 0x015A8016, 0x80C30F7F },  /*   -22,  346, 3967, -195 */
+    { 0x014D8015, 0x80BF0F87 },  /*   -21,  333, 3975, -191 */
+    { 0x013F8015, 0x80BB0F91 },  /*   -21,  319, 3985, -187 */
+    { 0x01328014, 0x80B60F98 },  /*   -20,  306, 3992, -182 */
+    { 0x01258013, 0x80B20FA0 },  /*   -19,  293, 4000, -178 */
+    { 0x01188012, 0x80AD0FA7 },  /*   -18,  280, 4007, -173 */
+    { 0x010B8011, 0x80A80FAE },  /*   -17,  267, 4014, -168 */
+    { 0x00FE8010, 0x80A30FB5 },  /*   -16,  254, 4021, -163 */
+    { 0x00F28010, 0x809E0FBC },  /*   -16,  242, 4028, -158 */
+    { 0x00E6800F, 0x80990FC2 },  /*   -15,  230, 4034, -153 */
+    { 0x00DA800E, 0x80930FC7 },  /*   -14,  218, 4039, -147 */
+    { 0x00CE800D, 0x808E0FCD },  /*   -13,  206, 4045, -142 */
+    { 0x00C2800D, 0x80880FD3 },  /*   -13,  194, 4051, -136 */
+    { 0x00B6800C, 0x80820FD8 },  /*   -12,  182, 4056, -130 */
+    { 0x00AB800B, 0x807C0FDC },  /*   -11,  171, 4060, -124 */
+    { 0x009F800A, 0x80760FE1 },  /*   -10,  159, 4065, -118 */
+    { 0x0094800A, 0x80700FE6 },  /*   -10,  148, 4070, -112 */
+    { 0x00898009, 0x80690FE9 },  /*    -9,  137, 4073, -105 */
+    { 0x007E8008, 0x80630FED },  /*    -8,  126, 4077,  -99 */
+    { 0x00748007, 0x805C0FEF },  /*    -7,  116, 4079,  -92 */
+    { 0x00698007, 0x80550FF3 },  /*    -7,  105, 4083,  -85 */
+    { 0x005F8006, 0x804E0FF5 },  /*    -6,   95, 4085,  -78 */
+    { 0x00558005, 0x80470FF7 },  /*    -5,   85, 4087,  -71 */
+    { 0x004B8005, 0x80400FFA },  /*    -5,   75, 4090,  -64 */
+    { 0x00418004, 0x80380FFB },  /*    -4,   65, 4091,  -56 */
+    { 0x00378003, 0x80310FFD },  /*    -3,   55, 4093,  -49 */
+    { 0x002E8003, 0x80290FFE },  /*    -3,   46, 4094,  -41 */
+    { 0x00238002, 0x80211000 },  /*    -2,   35, 4096,  -33 */
+    { 0x001A8001, 0x80191000 },  /*    -1,   26, 4096,  -25 */
+    { 0x00118001, 0x80101000 },  /*    -1,   17, 4096,  -16 */
+    { 0x00080000, 0x80081000 },  /*     0,    8, 4096,   -8 */
+};
+
+long CimarronVideoFilter128[][2] =
+{
+	{ 0x10000000, 0x00000000 },  /*     0, 4096,    0,    0 */
+    { 0x10018011, 0x80010011 },  /*   -17, 4097,   17,   -1 */
+    { 0x10008021, 0x80020023 },  /*   -33, 4096,   35,   -2 */
+    { 0x0FFE8031, 0x80030036 },  /*   -49, 4094,   54,   -3 */
+    { 0x0FFB8040, 0x8005004A },  /*   -64, 4091,   74,   -5 */
+    { 0x0FF6804E, 0x8006005E },  /*   -78, 4086,   94,   -6 */
+    { 0x0FF0805C, 0x80070073 },  /*   -92, 4080,  115,   -7 */
+    { 0x0FEB806A, 0x80090088 },  /*  -106, 4075,  136,   -9 */
+    { 0x0FE18076, 0x800A009F },  /*  -118, 4065,  159,  -10 */
+    { 0x0FD98082, 0x800C00B5 },  /*  -130, 4057,  181,  -12 */
+    { 0x0FCE808E, 0x800D00CD },  /*  -142, 4046,  205,  -13 */
+    { 0x0FC38099, 0x800F00E5 },  /*  -153, 4035,  229,  -15 */
+    { 0x0FB680A4, 0x801000FE },  /*  -164, 4022,  254,  -16 */
+    { 0x0FA880AD, 0x80120117 },  /*  -173, 4008,  279,  -18 */
+    { 0x0F9A80B7, 0x80140131 },  /*  -183, 3994,  305,  -20 */
+    { 0x0F8980C0, 0x8015014C },  /*  -192, 3977,  332,  -21 */
+    { 0x0F7880C8, 0x80170167 },  /*  -200, 3960,  359,  -23 */
+    { 0x0F6680D0, 0x80190183 },  /*  -208, 3942,  387,  -25 */
+    { 0x0F5280D7, 0x801B01A0 },  /*  -215, 3922,  416,  -27 */
+    { 0x0F3E80DE, 0x801D01BD },  /*  -222, 3902,  445,  -29 */
+    { 0x0F2880E4, 0x801F01DB },  /*  -228, 3880,  475,  -31 */
+    { 0x0F1180EA, 0x802101FA },  /*  -234, 3857,  506,  -33 */
+    { 0x0EF880EE, 0x80220218 },  /*  -238, 3832,  536,  -34 */
+    { 0x0EDF80F3, 0x80240238 },  /*  -243, 3807,  568,  -36 */
+    { 0x0EC680F7, 0x80270258 },  /*  -247, 3782,  600,  -39 */
+    { 0x0EAB80FB, 0x80290279 },  /*  -251, 3755,  633,  -41 */
+    { 0x0E9080FF, 0x802B029A },  /*  -255, 3728,  666,  -43 */
+    { 0x0E748102, 0x802E02BC },  /*  -258, 3700,  700,  -46 */
+    { 0x0E588105, 0x803102DE },  /*  -261, 3672,  734,  -49 */
+    { 0x0E388107, 0x80330302 },  /*  -263, 3640,  770,  -51 */
+    { 0x0E1A8109, 0x80360325 },  /*  -265, 3610,  805,  -54 */
+    { 0x0DFB810B, 0x80390349 },  /*  -267, 3579,  841,  -57 */
+    { 0x0DDB810C, 0x803C036D },  /*  -268, 3547,  877,  -60 */
+    { 0x0DBA810D, 0x803F0392 },  /*  -269, 3514,  914,  -63 */
+    { 0x0D98810E, 0x804203B8 },  /*  -270, 3480,  952,  -66 */
+    { 0x0D74810D, 0x804503DE },  /*  -269, 3444,  990,  -69 */
+    { 0x0D50810D, 0x80480405 },  /*  -269, 3408, 1029,  -72 */
+    { 0x0D2C810C, 0x804B042B },  /*  -268, 3372, 1067,  -75 */
+    { 0x0D08810C, 0x804F0453 },  /*  -268, 3336, 1107,  -79 */
+    { 0x0CE3810B, 0x8052047A },  /*  -267, 3299, 1146,  -82 */
+    { 0x0CBD810A, 0x805604A3 },  /*  -266, 3261, 1187,  -86 */
+    { 0x0C968108, 0x805904CB },  /*  -264, 3222, 1227,  -89 */
+    { 0x0C708107, 0x805D04F4 },  /*  -263, 3184, 1268,  -93 */
+    { 0x0C488105, 0x8061051E },  /*  -261, 3144, 1310,  -97 */
+    { 0x0C208103, 0x80640547 },  /*  -259, 3104, 1351, -100 */
+    { 0x0BF78100, 0x80680571 },  /*  -256, 3063, 1393, -104 */
+    { 0x0BCF80FE, 0x806C059B },  /*  -254, 3023, 1435, -108 */
+    { 0x0BA480FA, 0x807005C6 },  /*  -250, 2980, 1478, -112 */
+    { 0x0B7A80F7, 0x807405F1 },  /*  -247, 2938, 1521, -116 */
+    { 0x0B4F80F4, 0x8077061C },  /*  -244, 2895, 1564, -119 */
+    { 0x0B2580F1, 0x807C0648 },  /*  -241, 2853, 1608, -124 */
+    { 0x0AFA80ED, 0x80800673 },  /*  -237, 2810, 1651, -128 */
+    { 0x0ACF80EA, 0x8084069F },  /*  -234, 2767, 1695, -132 */
+    { 0x0AA380E6, 0x808806CB },  /*  -230, 2723, 1739, -136 */
+    { 0x0A7880E2, 0x808D06F7 },  /*  -226, 2680, 1783, -141 */
+    { 0x0A4C80DF, 0x80910724 },  /*  -223, 2636, 1828, -145 */
+    { 0x0A2080DB, 0x80960751 },  /*  -219, 2592, 1873, -150 */
+    { 0x09F480D7, 0x809A077D },  /*  -215, 2548, 1917, -154 */
+    { 0x09C780D2, 0x809F07AA },  /*  -210, 2503, 1962, -159 */
+    { 0x099A80CE, 0x80A307D7 },  /*  -206, 2458, 2007, -163 */
+    { 0x096D80CA, 0x80A70804 },  /*  -202, 2413, 2052, -167 */
+    { 0x094180C6, 0x80AC0831 },  /*  -198, 2369, 2097, -172 */
+    { 0x091380C1, 0x80B0085E },  /*  -193, 2323, 2142, -176 */
+    { 0x08E780BE, 0x80B5088C },  /*  -190, 2279, 2188, -181 */
+    { 0x08B980B9, 0x80B908B9 },  /*  -185, 2233, 2233, -185 */
+    { 0x088C80B5, 0x80BE08E7 },  /*  -181, 2188, 2279, -190 */
+    { 0x085E80B0, 0x80C10913 },  /*  -176, 2142, 2323, -193 */
+    { 0x083180AC, 0x80C60941 },  /*  -172, 2097, 2369, -198 */
+    { 0x080480A7, 0x80CA096D },  /*  -167, 2052, 2413, -202 */
+    { 0x07D780A3, 0x80CE099A },  /*  -163, 2007, 2458, -206 */
+    { 0x07AA809F, 0x80D209C7 },  /*  -159, 1962, 2503, -210 */
+    { 0x077D809A, 0x80D709F4 },  /*  -154, 1917, 2548, -215 */
+    { 0x07518096, 0x80DB0A20 },  /*  -150, 1873, 2592, -219 */
+    { 0x07248091, 0x80DF0A4C },  /*  -145, 1828, 2636, -223 */
+    { 0x06F7808D, 0x80E20A78 },  /*  -141, 1783, 2680, -226 */
+    { 0x06CA8088, 0x80E60AA4 },  /*  -136, 1738, 2724, -230 */
+    { 0x069E8084, 0x80EA0AD0 },  /*  -132, 1694, 2768, -234 */
+    { 0x06738080, 0x80ED0AFA },  /*  -128, 1651, 2810, -237 */
+    { 0x0647807C, 0x80F10B26 },  /*  -124, 1607, 2854, -241 */
+    { 0x061B8077, 0x80F40B50 },  /*  -119, 1563, 2896, -244 */
+    { 0x05F18074, 0x80F70B7A },  /*  -116, 1521, 2938, -247 */
+    { 0x05C68070, 0x80FA0BA4 },  /*  -112, 1478, 2980, -250 */
+    { 0x059C806C, 0x80FE0BCE },  /*  -108, 1436, 3022, -254 */
+    { 0x05728068, 0x81000BF6 },  /*  -104, 1394, 3062, -256 */
+    { 0x05478064, 0x81030C20 },  /*  -100, 1351, 3104, -259 */
+    { 0x051E8061, 0x81050C48 },  /*   -97, 1310, 3144, -261 */
+    { 0x04F4805D, 0x81070C70 },  /*   -93, 1268, 3184, -263 */
+    { 0x04CB8059, 0x81080C96 },  /*   -89, 1227, 3222, -264 */
+    { 0x04A38056, 0x810A0CBD },  /*   -86, 1187, 3261, -266 */
+    { 0x047A8052, 0x810B0CE3 },  /*   -82, 1146, 3299, -267 */
+    { 0x0453804F, 0x810C0D08 },  /*   -79, 1107, 3336, -268 */
+    { 0x042B804B, 0x810C0D2C },  /*   -75, 1067, 3372, -268 */
+    { 0x04048048, 0x810D0D51 },  /*   -72, 1028, 3409, -269 */
+    { 0x03DE8045, 0x810D0D74 },  /*   -69,  990, 3444, -269 */
+    { 0x03B88042, 0x810E0D98 },  /*   -66,  952, 3480, -270 */
+    { 0x0393803F, 0x810D0DB9 },  /*   -63,  915, 3513, -269 */
+    { 0x036E803C, 0x810C0DDA },  /*   -60,  878, 3546, -268 */
+    { 0x03498039, 0x810B0DFB },  /*   -57,  841, 3579, -267 */
+    { 0x03258036, 0x81090E1A },  /*   -54,  805, 3610, -265 */
+    { 0x03018033, 0x81070E39 },  /*   -51,  769, 3641, -263 */
+    { 0x02DE8031, 0x81050E58 },  /*   -49,  734, 3672, -261 */
+    { 0x02BC802E, 0x81020E74 },  /*   -46,  700, 3700, -258 */
+    { 0x0299802B, 0x80FF0E91 },  /*   -43,  665, 3729, -255 */
+    { 0x02788029, 0x80FB0EAC },  /*   -41,  632, 3756, -251 */
+    { 0x02578027, 0x80F70EC7 },  /*   -39,  599, 3783, -247 */
+    { 0x02378024, 0x80F30EE0 },  /*   -36,  567, 3808, -243 */
+    { 0x02178022, 0x80EE0EF9 },  /*   -34,  535, 3833, -238 */
+    { 0x01FA8021, 0x80EA0F11 },  /*   -33,  506, 3857, -234 */
+    { 0x01DC801F, 0x80E40F27 },  /*   -31,  476, 3879, -228 */
+    { 0x01BE801D, 0x80DE0F3D },  /*   -29,  446, 3901, -222 */
+    { 0x01A1801B, 0x80D70F51 },  /*   -27,  417, 3921, -215 */
+    { 0x01848019, 0x80D00F65 },  /*   -25,  388, 3941, -208 */
+    { 0x01688017, 0x80C80F77 },  /*   -23,  360, 3959, -200 */
+    { 0x014D8015, 0x80C00F88 },  /*   -21,  333, 3976, -192 */
+    { 0x01328014, 0x80B70F99 },  /*   -20,  306, 3993, -183 */
+    { 0x01188012, 0x80AD0FA7 },  /*   -18,  280, 4007, -173 */
+    { 0x00FF8010, 0x80A40FB5 },  /*   -16,  255, 4021, -164 */
+    { 0x00E6800F, 0x80990FC2 },  /*   -15,  230, 4034, -153 */
+    { 0x00CE800D, 0x808E0FCD },  /*   -13,  206, 4045, -142 */
+    { 0x00B6800C, 0x80820FD8 },  /*   -12,  182, 4056, -130 */
+    { 0x00A0800A, 0x80760FE0 },  /*   -10,  160, 4064, -118 */
+    { 0x00898009, 0x806A0FEA },  /*    -9,  137, 4074, -106 */
+    { 0x00748007, 0x805C0FEF },  /*    -7,  116, 4079,  -92 */
+    { 0x005F8006, 0x804E0FF5 },  /*    -6,   95, 4085,  -78 */
+    { 0x004B8005, 0x80400FFA },  /*    -5,   75, 4090,  -64 */
+    { 0x00378003, 0x80310FFD },  /*    -3,   55, 4093,  -49 */
+    { 0x00238002, 0x80211000 },  /*    -2,   35, 4096,  -33 */
+    { 0x00118001, 0x80111001 },  /*    -1,   17, 4097,  -17 */
+    { 0x10000000, 0x00000000 },  /*     0, 4096,    0,    0 */
+    { 0x10018011, 0x80010011 },  /*   -17, 4097,   17,   -1 */
+    { 0x10008021, 0x80020023 },  /*   -33, 4096,   35,   -2 */
+    { 0x0FFE8031, 0x80030036 },  /*   -49, 4094,   54,   -3 */
+    { 0x0FFB8040, 0x8005004A },  /*   -64, 4091,   74,   -5 */
+    { 0x0FF6804E, 0x8006005E },  /*   -78, 4086,   94,   -6 */
+    { 0x0FF0805C, 0x80070073 },  /*   -92, 4080,  115,   -7 */
+    { 0x0FEB806A, 0x80090088 },  /*  -106, 4075,  136,   -9 */
+    { 0x0FE18076, 0x800A009F },  /*  -118, 4065,  159,  -10 */
+    { 0x0FD98082, 0x800C00B5 },  /*  -130, 4057,  181,  -12 */
+    { 0x0FCE808E, 0x800D00CD },  /*  -142, 4046,  205,  -13 */
+    { 0x0FC38099, 0x800F00E5 },  /*  -153, 4035,  229,  -15 */
+    { 0x0FB680A4, 0x801000FE },  /*  -164, 4022,  254,  -16 */
+    { 0x0FA880AD, 0x80120117 },  /*  -173, 4008,  279,  -18 */
+    { 0x0F9A80B7, 0x80140131 },  /*  -183, 3994,  305,  -20 */
+    { 0x0F8980C0, 0x8015014C },  /*  -192, 3977,  332,  -21 */
+    { 0x0F7880C8, 0x80170167 },  /*  -200, 3960,  359,  -23 */
+    { 0x0F6680D0, 0x80190183 },  /*  -208, 3942,  387,  -25 */
+    { 0x0F5280D7, 0x801B01A0 },  /*  -215, 3922,  416,  -27 */
+    { 0x0F3E80DE, 0x801D01BD },  /*  -222, 3902,  445,  -29 */
+    { 0x0F2880E4, 0x801F01DB },  /*  -228, 3880,  475,  -31 */
+    { 0x0F1180EA, 0x802101FA },  /*  -234, 3857,  506,  -33 */
+    { 0x0EF880EE, 0x80220218 },  /*  -238, 3832,  536,  -34 */
+    { 0x0EDF80F3, 0x80240238 },  /*  -243, 3807,  568,  -36 */
+    { 0x0EC680F7, 0x80270258 },  /*  -247, 3782,  600,  -39 */
+    { 0x0EAB80FB, 0x80290279 },  /*  -251, 3755,  633,  -41 */
+    { 0x0E9080FF, 0x802B029A },  /*  -255, 3728,  666,  -43 */
+    { 0x0E748102, 0x802E02BC },  /*  -258, 3700,  700,  -46 */
+    { 0x0E588105, 0x803102DE },  /*  -261, 3672,  734,  -49 */
+    { 0x0E388107, 0x80330302 },  /*  -263, 3640,  770,  -51 */
+    { 0x0E1A8109, 0x80360325 },  /*  -265, 3610,  805,  -54 */
+    { 0x0DFB810B, 0x80390349 },  /*  -267, 3579,  841,  -57 */
+    { 0x0DDB810C, 0x803C036D },  /*  -268, 3547,  877,  -60 */
+    { 0x0DBA810D, 0x803F0392 },  /*  -269, 3514,  914,  -63 */
+    { 0x0D98810E, 0x804203B8 },  /*  -270, 3480,  952,  -66 */
+    { 0x0D74810D, 0x804503DE },  /*  -269, 3444,  990,  -69 */
+    { 0x0D50810D, 0x80480405 },  /*  -269, 3408, 1029,  -72 */
+    { 0x0D2C810C, 0x804B042B },  /*  -268, 3372, 1067,  -75 */
+    { 0x0D08810C, 0x804F0453 },  /*  -268, 3336, 1107,  -79 */
+    { 0x0CE3810B, 0x8052047A },  /*  -267, 3299, 1146,  -82 */
+    { 0x0CBD810A, 0x805604A3 },  /*  -266, 3261, 1187,  -86 */
+    { 0x0C968108, 0x805904CB },  /*  -264, 3222, 1227,  -89 */
+    { 0x0C708107, 0x805D04F4 },  /*  -263, 3184, 1268,  -93 */
+    { 0x0C488105, 0x8061051E },  /*  -261, 3144, 1310,  -97 */
+    { 0x0C208103, 0x80640547 },  /*  -259, 3104, 1351, -100 */
+    { 0x0BF78100, 0x80680571 },  /*  -256, 3063, 1393, -104 */
+    { 0x0BCF80FE, 0x806C059B },  /*  -254, 3023, 1435, -108 */
+    { 0x0BA480FA, 0x807005C6 },  /*  -250, 2980, 1478, -112 */
+    { 0x0B7A80F7, 0x807405F1 },  /*  -247, 2938, 1521, -116 */
+    { 0x0B4F80F4, 0x8077061C },  /*  -244, 2895, 1564, -119 */
+    { 0x0B2580F1, 0x807C0648 },  /*  -241, 2853, 1608, -124 */
+    { 0x0AFA80ED, 0x80800673 },  /*  -237, 2810, 1651, -128 */
+    { 0x0ACF80EA, 0x8084069F },  /*  -234, 2767, 1695, -132 */
+    { 0x0AA380E6, 0x808806CB },  /*  -230, 2723, 1739, -136 */
+    { 0x0A7880E2, 0x808D06F7 },  /*  -226, 2680, 1783, -141 */
+    { 0x0A4C80DF, 0x80910724 },  /*  -223, 2636, 1828, -145 */
+    { 0x0A2080DB, 0x80960751 },  /*  -219, 2592, 1873, -150 */
+    { 0x09F480D7, 0x809A077D },  /*  -215, 2548, 1917, -154 */
+    { 0x09C780D2, 0x809F07AA },  /*  -210, 2503, 1962, -159 */
+    { 0x099A80CE, 0x80A307D7 },  /*  -206, 2458, 2007, -163 */
+    { 0x096D80CA, 0x80A70804 },  /*  -202, 2413, 2052, -167 */
+    { 0x094180C6, 0x80AC0831 },  /*  -198, 2369, 2097, -172 */
+    { 0x091380C1, 0x80B0085E },  /*  -193, 2323, 2142, -176 */
+    { 0x08E780BE, 0x80B5088C },  /*  -190, 2279, 2188, -181 */
+    { 0x08B980B9, 0x80B908B9 },  /*  -185, 2233, 2233, -185 */
+    { 0x088C80B5, 0x80BE08E7 },  /*  -181, 2188, 2279, -190 */
+    { 0x085E80B0, 0x80C10913 },  /*  -176, 2142, 2323, -193 */
+    { 0x083180AC, 0x80C60941 },  /*  -172, 2097, 2369, -198 */
+    { 0x080480A7, 0x80CA096D },  /*  -167, 2052, 2413, -202 */
+    { 0x07D780A3, 0x80CE099A },  /*  -163, 2007, 2458, -206 */
+    { 0x07AA809F, 0x80D209C7 },  /*  -159, 1962, 2503, -210 */
+    { 0x077D809A, 0x80D709F4 },  /*  -154, 1917, 2548, -215 */
+    { 0x07518096, 0x80DB0A20 },  /*  -150, 1873, 2592, -219 */
+    { 0x07248091, 0x80DF0A4C },  /*  -145, 1828, 2636, -223 */
+    { 0x06F7808D, 0x80E20A78 },  /*  -141, 1783, 2680, -226 */
+    { 0x06CA8088, 0x80E60AA4 },  /*  -136, 1738, 2724, -230 */
+    { 0x069E8084, 0x80EA0AD0 },  /*  -132, 1694, 2768, -234 */
+    { 0x06738080, 0x80ED0AFA },  /*  -128, 1651, 2810, -237 */
+    { 0x0647807C, 0x80F10B26 },  /*  -124, 1607, 2854, -241 */
+    { 0x061B8077, 0x80F40B50 },  /*  -119, 1563, 2896, -244 */
+    { 0x05F18074, 0x80F70B7A },  /*  -116, 1521, 2938, -247 */
+    { 0x05C68070, 0x80FA0BA4 },  /*  -112, 1478, 2980, -250 */
+    { 0x059C806C, 0x80FE0BCE },  /*  -108, 1436, 3022, -254 */
+    { 0x05728068, 0x81000BF6 },  /*  -104, 1394, 3062, -256 */
+    { 0x05478064, 0x81030C20 },  /*  -100, 1351, 3104, -259 */
+    { 0x051E8061, 0x81050C48 },  /*   -97, 1310, 3144, -261 */
+    { 0x04F4805D, 0x81070C70 },  /*   -93, 1268, 3184, -263 */
+    { 0x04CB8059, 0x81080C96 },  /*   -89, 1227, 3222, -264 */
+    { 0x04A38056, 0x810A0CBD },  /*   -86, 1187, 3261, -266 */
+    { 0x047A8052, 0x810B0CE3 },  /*   -82, 1146, 3299, -267 */
+    { 0x0453804F, 0x810C0D08 },  /*   -79, 1107, 3336, -268 */
+    { 0x042B804B, 0x810C0D2C },  /*   -75, 1067, 3372, -268 */
+    { 0x04048048, 0x810D0D51 },  /*   -72, 1028, 3409, -269 */
+    { 0x03DE8045, 0x810D0D74 },  /*   -69,  990, 3444, -269 */
+    { 0x03B88042, 0x810E0D98 },  /*   -66,  952, 3480, -270 */
+    { 0x0393803F, 0x810D0DB9 },  /*   -63,  915, 3513, -269 */
+    { 0x036E803C, 0x810C0DDA },  /*   -60,  878, 3546, -268 */
+    { 0x03498039, 0x810B0DFB },  /*   -57,  841, 3579, -267 */
+    { 0x03258036, 0x81090E1A },  /*   -54,  805, 3610, -265 */
+    { 0x03018033, 0x81070E39 },  /*   -51,  769, 3641, -263 */
+    { 0x02DE8031, 0x81050E58 },  /*   -49,  734, 3672, -261 */
+    { 0x02BC802E, 0x81020E74 },  /*   -46,  700, 3700, -258 */
+    { 0x0299802B, 0x80FF0E91 },  /*   -43,  665, 3729, -255 */
+    { 0x02788029, 0x80FB0EAC },  /*   -41,  632, 3756, -251 */
+    { 0x02578027, 0x80F70EC7 },  /*   -39,  599, 3783, -247 */
+    { 0x02378024, 0x80F30EE0 },  /*   -36,  567, 3808, -243 */
+    { 0x02178022, 0x80EE0EF9 },  /*   -34,  535, 3833, -238 */
+    { 0x01FA8021, 0x80EA0F11 },  /*   -33,  506, 3857, -234 */
+    { 0x01DC801F, 0x80E40F27 },  /*   -31,  476, 3879, -228 */
+    { 0x01BE801D, 0x80DE0F3D },  /*   -29,  446, 3901, -222 */
+    { 0x01A1801B, 0x80D70F51 },  /*   -27,  417, 3921, -215 */
+    { 0x01848019, 0x80D00F65 },  /*   -25,  388, 3941, -208 */
+    { 0x01688017, 0x80C80F77 },  /*   -23,  360, 3959, -200 */
+    { 0x014D8015, 0x80C00F88 },  /*   -21,  333, 3976, -192 */
+    { 0x01328014, 0x80B70F99 },  /*   -20,  306, 3993, -183 */
+    { 0x01188012, 0x80AD0FA7 },  /*   -18,  280, 4007, -173 */
+    { 0x00FF8010, 0x80A40FB5 },  /*   -16,  255, 4021, -164 */
+    { 0x00E6800F, 0x80990FC2 },  /*   -15,  230, 4034, -153 */
+    { 0x00CE800D, 0x808E0FCD },  /*   -13,  206, 4045, -142 */
+    { 0x00B6800C, 0x80820FD8 },  /*   -12,  182, 4056, -130 */
+    { 0x00A0800A, 0x80760FE0 },  /*   -10,  160, 4064, -118 */
+    { 0x00898009, 0x806A0FEA },  /*    -9,  137, 4074, -106 */
+    { 0x00748007, 0x805C0FEF },  /*    -7,  116, 4079,  -92 */
+    { 0x005F8006, 0x804E0FF5 },  /*    -6,   95, 4085,  -78 */
+    { 0x004B8005, 0x80400FFA },  /*    -5,   75, 4090,  -64 */
+    { 0x00378003, 0x80310FFD },  /*    -3,   55, 4093,  -49 */
+    { 0x00238002, 0x80211000 },  /*    -2,   35, 4096,  -33 */
+    { 0x00118001, 0x80111001 },  /*    -1,   17, 4097,  -17 */
+};
diff --git a/lib/cimarron/cim/cim_gp.c b/lib/cimarron/cim/cim_gp.c
new file mode 100644
index 0000000..a1b2dd3
--- /dev/null
+++ b/lib/cimarron/cim/cim_gp.c
@@ -0,0 +1,3442 @@
+ /*
+  * <LIC_AMD_STD>
+  * Copyright (C) 2005 Advanced Micro Devices, Inc.  All Rights Reserved.
+  * </LIC_AMD_STD>
+  *
+  * <CTL_AMD_STD>
+  * </CTL_AMD_STD>
+  *
+  * <DOC_AMD_STD>
+  * Cimarron graphics processor routines.  These routines program the graphics
+  * hardware using the graphics command buffer.
+  * </DOC_AMD_STD>
+  *
+  */
+
+/*---------------------*/
+/* CIMARRON GP GLOBALS */
+/*---------------------*/
+
+CIMARRON_STATIC unsigned long gp3_bpp         = 0;
+CIMARRON_STATIC unsigned long gp3_ch3_bpp     = 0;
+CIMARRON_STATIC unsigned long gp3_pat_origin  = 0;
+CIMARRON_STATIC unsigned long gp3_buffer_lead = 0;
+CIMARRON_STATIC unsigned long gp3_cmd_header;
+CIMARRON_STATIC unsigned long gp3_cmd_top;
+CIMARRON_STATIC unsigned long gp3_cmd_bottom;
+CIMARRON_STATIC unsigned long gp3_cmd_current;
+CIMARRON_STATIC unsigned long gp3_cmd_next;
+CIMARRON_STATIC unsigned long gp3_blt_mode;
+CIMARRON_STATIC unsigned long gp3_vec_mode;
+CIMARRON_STATIC unsigned long gp3_raster_mode;
+CIMARRON_STATIC unsigned long gp3_pix_shift;
+CIMARRON_STATIC unsigned long gp3_ch3_pat;
+CIMARRON_STATIC unsigned long gp3_blt;
+CIMARRON_STATIC unsigned long gp3_blt_flags;
+CIMARRON_STATIC unsigned long gp3_src_stride;
+CIMARRON_STATIC unsigned long gp3_dst_stride;
+CIMARRON_STATIC unsigned long gp3_src_format;
+CIMARRON_STATIC unsigned long gp3_src_pix_shift;
+CIMARRON_STATIC unsigned long gp3_pat_format;
+CIMARRON_STATIC unsigned long gp3_pat_pix_shift;
+CIMARRON_STATIC unsigned long gp3_fb_base;
+CIMARRON_STATIC unsigned long gp3_vector_pattern_color;
+CIMARRON_STATIC unsigned long gp3_scratch_base;
+CIMARRON_STATIC unsigned long gp3_base_register;
+CIMARRON_STATIC unsigned long gp3_vec_pat;
+
+/*---------------------------------------------------------------------------
+ * gp_set_limit_on_buffer_lead
+ *
+ * This routine is used to specify the maximum number of bytes in the command
+ * buffer by which software can lead the graphics processor.  When declaring
+ * a BLT with the CIMGP_BLTFLAGS_LIMITBUFFER flag set, Cimarron will wait until
+ * the command buffer read and write pointers differ by no more than 'lead'
+ * bytes.  This can be useful to limit the time lag possible when creating a
+ * command buffer full of simple BLT commands.
+ *-------------------------------------------------------------------------*/
+
+void gp_set_limit_on_buffer_lead (unsigned long lead)
+{	
+	gp3_buffer_lead = lead;
+}
+
+/*---------------------------------------------------------------------------
+ * gp_set_command_buffer_base
+ *
+ * This routine is used to program the command buffer region in physical
+ * memory.  The command buffer start address must be 1MB aligned. start and
+ * stop refer to endpoints within the associated 16MB region.  Command buffers
+ * larger than 16MB are not supported.
+ *-------------------------------------------------------------------------*/
+
+void gp_set_command_buffer_base (unsigned long address, unsigned long start,
+	unsigned long stop)
+{	
+	Q_WORD msr_value;
+
+	/* WAIT FOR IDLE */
+	/* Obviously, we cannot change the command buffer pointer while the GP */
+	/* is currently fetching commands.                                     */
+
+	gp_wait_until_idle();
+
+    /* WRITE THE COMMAND BUFFER BASE */
+
+	msr_read64 (MSR_DEVICE_GEODELX_GP, MSR_GEODELINK_CONFIG, &msr_value);
+	msr_value.low &= 0xF000FFFF;
+	msr_value.low |= (address >> 4) & 0x0FFF0000;
+	msr_write64 (MSR_DEVICE_GEODELX_GP, MSR_GEODELINK_CONFIG, &msr_value);
+
+    /* WRITE THE BASE OFFSETS */
+	/* We also reset the write and read pointers.  The hardware will */
+	/* automatically update the write pointer when the read pointer  */
+	/* is updated to prevent the hardware from getting confused when */
+	/* initializing a new command buffer.                            */
+
+	WRITE_GP32 (GP3_CMD_TOP, start);
+	WRITE_GP32 (GP3_CMD_BOT, stop);
+	WRITE_GP32 (GP3_CMD_READ, start);
+
+    /* SAVE THE BASE ADDRESSES */
+	/* These are used to determine the appropriate wrap point. */
+
+	gp3_cmd_current = gp3_cmd_top = start;
+	gp3_cmd_bottom  = stop;
+}
+
+/*---------------------------------------------------------------------------
+ * gp_set_frame_buffer_base
+ *
+ * This routine is used to program the base address of the frame buffer in
+ * physical memory.  The frame buffer address must be 16MB aligned.  Cimarron
+ * tracks the base address because the maximum frame buffer size may exceed
+ * 16MB. Any primitive will thus program the corresponding 16MB region into all
+ * base offset registers as well as program the offset into the 16MB region.
+ * The size parameter is provided to allow Cimarron to claim the last 1MB of
+ * space to be used as a scratch area for workarounds or expanded functionality.
+ *-------------------------------------------------------------------------*/
+
+void gp_set_frame_buffer_base (unsigned long address, unsigned long size)
+{	
+    gp3_scratch_base = size - GP3_SCRATCH_BUFFER_SIZE;
+	gp3_fb_base = address >> 24;
+    gp3_base_register = (gp3_fb_base << 24) | (gp3_fb_base << 14) | (gp3_fb_base << 4);
+    WRITE_GP32 (GP3_BASE_OFFSET, gp3_base_register);
+}
+
+/*---------------------------------------------------------------------------
+ * gp_set_bpp
+ *
+ * This routine sets the output BPP of the GP.  The BPP used by the GP does
+ * not have to match the display BPP, but that is usually the case.  The
+ * supported BPP values are as follows:
+ *
+ *    8  - palettized 8BPP
+ *    12 - 4:4:4:4
+ *    15 - 1:5:5:5
+ *    16 - 0:5:6:5
+ *    32 - 8:8:8:8
+ *-------------------------------------------------------------------------*/
+
+void gp_set_bpp (int bpp)
+{
+	/* STORE BPP */
+	/* The bpp is not updated until the next call to gp_set_raster_mode. */
+	/* This allows the gp_set_bpp call to happen outside of a BLT.  It   */
+	/* also implies that no registers need be written in this routine.   */
+	
+	switch(bpp)
+	{
+		case 8:	
+			gp3_bpp       = GP3_RM_BPPFMT_332;
+			gp3_ch3_bpp   = GP3_CH3_SRC_3_3_2;
+			gp3_pix_shift = 0;
+			break;
+		case 12:
+			gp3_bpp       = GP3_RM_BPPFMT_4444;
+			gp3_ch3_bpp   = GP3_CH3_SRC_4_4_4_4;
+			gp3_pix_shift = 1;
+			break;
+		case 15:
+			gp3_bpp       = GP3_RM_BPPFMT_1555;
+			gp3_ch3_bpp   = GP3_CH3_SRC_1_5_5_5;
+			gp3_pix_shift = 1;
+			break;
+		case 16:
+			gp3_bpp       = GP3_RM_BPPFMT_565;
+			gp3_ch3_bpp   = GP3_CH3_SRC_0_5_6_5;
+			gp3_pix_shift = 1;
+			break;
+        case 24:
+        case 32:
+			gp3_bpp       = GP3_RM_BPPFMT_8888;
+			gp3_ch3_bpp   = GP3_CH3_SRC_8_8_8_8;
+			gp3_pix_shift = 2;
+			break;
+		default:
+			gp3_bpp       = GP3_RM_BPPFMT_332;
+			gp3_ch3_bpp   = GP3_CH3_SRC_3_3_2;
+			gp3_pix_shift = 0;
+			break;
+	}
+}
+
+/*---------------------------------------------------------------------------
+ * gp_declare_blt
+ *
+ * This routine is used to prepare for a 2D BLT.  Its primary function
+ * is to verify that enough room is available in the command buffer
+ * to hold a BLT command.  This command can be called multiple times if
+ * necessary.  For example, if a function calls this routine on entry, but
+ * later realizes that a LUT load command must be executed before the BLT,
+ * the application could call gp_set_color_pattern and then call
+ * gp_declare_blt to declare the BLT.  This is possible because the hardware
+ * buffer pointer is not updated until a new BLT is actually executed.  An
+ * application must take care not to call any routines that perform a buffer
+ * command, (such as gp_set_color_pattern) between gp_declare_blt and the
+ * routines used to program the BLT parameters.  In addition to checking for
+ * available space, this routine also performs the following actions:
+ *    - Sets the wrap bit if this BLT will pass close to the end of the buffer.
+ *    - Writes the command header.
+ *
+ * The available flags are defined as follows:
+ *   0x01 - Preserve the LUT
+ *   0x02 - Preserve the color pattern.
+ *   0x04 - Enable prefetch.
+ *-------------------------------------------------------------------------*/
+
+void gp_declare_blt (unsigned long flags)
+{	
+	unsigned long temp;
+
+	gp3_blt = 1;
+	gp3_blt_flags = flags;
+
+	/* SET ADDRESS OF NEXT COMMAND */
+	/* A summary of the command buffer logic is as follows:           */
+	/*  - If after a basic BLT we will not have room for the largest  */
+	/*    command (a full line of host source data), we set the wrap  */
+	/*    bit.  This will waste up to a whopping 8K of command buffer */
+	/*    space, but it simplifies the logic for all commands.        */
+	/* -  If we are wrapping, we have extra logic to ensure that we   */
+	/*    don't skip over the current GP read pointer.                */
+
+    gp3_cmd_next = gp3_cmd_current + GP3_BLT_COMMAND_SIZE;
+
+	/* CHECK WRAP CONDITION */
+
+	if ((gp3_cmd_bottom - gp3_cmd_next) <= GP3_MAX_COMMAND_SIZE)
+	{
+		gp3_cmd_next   = gp3_cmd_top;
+		gp3_cmd_header = GP3_BLT_HDR_TYPE | GP3_BLT_HDR_WRAP;
+
+		/* WAIT FOR HARDWARE */
+		/* When wrapping, we must take steps to ensure that we do not    */
+		/* wrap over the current hardware read pointer.  We do this by   */
+		/* verifying that the hardware is not between us and the end of  */
+		/* the command buffer.  We also have a special case to make sure */
+		/* that the hardware is not currently reading the top of the     */
+		/* command buffer.                                               */
+
+		GP3_WAIT_WRAP(temp);
+	}
+	else
+	{
+		gp3_cmd_header = GP3_BLT_HDR_TYPE;
+
+		/* WAIT FOR AVAILABLE SPACE */
+
+		GP3_WAIT_PRIMITIVE(temp);
+	}
+
+    if (flags & CIMGP_BLTFLAGS_LIMITBUFFER)
+    {
+        while (1)
+        {
+            temp = READ_GP32 (GP3_CMD_READ);
+            if (((gp3_cmd_current >= temp) && ((gp3_cmd_current - temp) <= gp3_buffer_lead)) ||
+                ((gp3_cmd_current <  temp) && ((gp3_cmd_current + (gp3_cmd_bottom - temp)) <= gp3_buffer_lead)))
+            {
+                break;
+            }
+        }
+    }
+
+	/* SET THE CURRENT BUFFER POINTER */
+	/* We initialize a pointer to the current buffer base to avoid an */
+	/* extra addition for every buffer write.                         */
+
+	cim_cmd_ptr = cim_cmd_base_ptr + gp3_cmd_current;
+
+    /* SET THE HAZARD BIT */
+
+    if (flags & CIMGP_BLTFLAGS_HAZARD)
+        gp3_cmd_header |= GP3_BLT_HDR_HAZARD_ENABLE;
+}
+
+/*---------------------------------------------------------------------------
+ * gp_declare_vector
+ *
+ * This routine is used to prepare for a 2D vector.  It has no other function
+ * except to verify that enough room is available in the command buffer
+ * to hold a vector command.  The same rules that apply to BLTs apply to
+ * vectors. (See the documentation for gp_declare_blt).
+ *-------------------------------------------------------------------------*/
+
+void gp_declare_vector (unsigned long flags)
+{
+	unsigned long temp;
+
+	gp3_blt = 0;
+    gp3_blt_flags = flags;
+	
+	/* SET ADDRESS OF NEXT COMMAND                            */
+	/* The logic to force a wrap during a vector is identical */
+	/* to the BLT logic.                                      */
+
+    /* ALLOCATE SPACE FOR AN ADDITIONAL VECTOR TO CLEAR THE BYTE ENABLES */
+
+    gp3_cmd_next = gp3_cmd_current + GP3_VECTOR_COMMAND_SIZE + GP3_VECTOR_COMMAND_SIZE + 32;
+
+	/* CHECK WRAP CONDITION */
+
+	if ((gp3_cmd_bottom - gp3_cmd_next) <= GP3_MAX_COMMAND_SIZE)
+	{
+		gp3_cmd_next   = gp3_cmd_top;
+		gp3_cmd_header = GP3_VEC_HDR_TYPE | GP3_VEC_HDR_WRAP;
+
+		/* CHECK WRAP CONDITION */
+
+		GP3_WAIT_WRAP(temp);
+	}
+	else
+	{
+		gp3_cmd_header = GP3_VEC_HDR_TYPE;
+
+		/* WAIT FOR AVAILABLE SPACE */
+
+		GP3_WAIT_PRIMITIVE(temp);
+
+        gp3_cmd_next -= GP3_VECTOR_COMMAND_SIZE + 32;
+	}
+
+    if (flags & CIMGP_BLTFLAGS_LIMITBUFFER)
+    {
+        while (1)
+        {
+            temp = READ_GP32 (GP3_CMD_READ);
+            if (((gp3_cmd_current >= temp) && ((gp3_cmd_current - temp) <= gp3_buffer_lead)) ||
+                ((gp3_cmd_current <  temp) && ((gp3_cmd_current + (gp3_cmd_bottom - temp)) <= gp3_buffer_lead)))
+            {
+                break;
+            }
+        }
+    }
+
+	cim_cmd_ptr = cim_cmd_base_ptr + gp3_cmd_current;
+
+    /* SET THE HAZARD BIT */
+
+    if (flags & CIMGP_BLTFLAGS_HAZARD)
+        gp3_cmd_header |= GP3_VEC_HDR_HAZARD_ENABLE;
+}
+
+/*---------------------------------------------------------------------------
+ * gp_write_parameters
+ *
+ * This routine is called to write all recent parameters to the hardware.
+ * This routine is necessary for any implementation that performs the setup
+ * for a BLT separate from the actual BLT.  An example would be a driver
+ * that prepares for multiple pattern fills by programming the ROP,
+ * pattern color and destination stride.  The driver might then perform
+ * repeated pattern fills with minimal effort.
+ *-------------------------------------------------------------------------*/
+
+void gp_write_parameters (void)
+{
+	/* WRITE THE COMMAND HEADER */
+	/* Command header is at offset 0 for BLTs and vectors */
+	
+	WRITE_COMMAND32 (GP3_BLT_CMD_HEADER, gp3_cmd_header);
+	
+	/* INCREMENT THE CURRENT WRITE POINTER */
+
+	gp3_cmd_current = gp3_cmd_next;
+
+	/* UPDATE THE GP WRITE POINTER */
+
+	WRITE_GP32 (GP3_CMD_WRITE, gp3_cmd_current);
+}
+
+/*---------------------------------------------------------------------------
+ * gp_set_raster_operation
+ *
+ * This is generally the first routine called when programming a BLT.  This
+ * routine performs the following functions:
+ *   - Sets the initial value of the GP3_RASTER_MODE register in the buffer.
+ *   - Clears any 8x8 pattern if the ROP does not involve pattern data.
+ *-------------------------------------------------------------------------*/
+
+void gp_set_raster_operation (unsigned char ROP)
+{
+	gp3_cmd_header |= GP3_BLT_HDR_RASTER_ENABLE;
+
+	/* WRITE THE RASTER MODE REGISTER                                   */
+	/* This register is in the same location in BLT and vector commands */
+
+	gp3_raster_mode = gp3_bpp | (unsigned long)ROP;
+	WRITE_COMMAND32 (GP3_BLT_RASTER_MODE, gp3_raster_mode);
+
+	/* CHECK IF DESTINATION IS REQUIRED */
+
+	if ((ROP & 0x55) ^ ((ROP >> 1) & 0x55))
+	{
+		gp3_blt_mode = GP3_BM_DST_REQ;
+		gp3_vec_mode = GP3_VM_DST_REQ;
+	}
+	else
+	{
+		gp3_blt_mode = gp3_vec_mode = 0;
+	}
+}
+
+/*----------------------------------------------------------------------------
+ * gp_set_alpha_operation
+ *
+ * BLTs are generally one of two types, a ROPed BLT or a BLT composited using
+ * alpha blending.  For the latter, this routine is used to configure the
+ * mathematical function used to create the blended output.  This routine
+ * should generally be called first when programming a BLT.  The available
+ * parameters mirror the hardware and are described as follows:
+ *
+ * alpha_operation =
+ *   0 - alpha * A
+ *   1 - (1 - alpha) * B
+ *   2 - A + (1 - alpha)*B
+ *   3 - alpha*A + (1 - alpha)*B
+ *
+ * alpha_type =
+ *   0 - alpha component of channel A
+ *   1 - alpha component of channel B
+ *   2 - Constant alpha
+ *   3 - Constant 1
+ *   4 - The color components of channel A
+ *   5 - The color components of channel B
+ *   6 - Alpha comes from the alpha channel of the source before the source undergoes
+ *       color conversion.
+ *
+ * channel =
+ *   0 - Channel A = source, channel B = destination
+ *   1 - Channel B = source, channel A = destination
+ *
+ * apply_alpha =
+ *   1 - Apply alpha blend to only the RGB portion of the pixel.  This must be
+ *       set when the source or destination format do not include an alpha channel.
+ *   2 - Apply alpha blend only to the alpha portion of the pixel.  This implies
+ *       that both destination and source include an alpha channel.
+ *   3 - Apply alpha blend to both the RGB and alpha portions of the pixel.
+ *
+ * Alpha-blended vectors are not currently supported.
+ *-------------------------------------------------------------------------*/
+
+void gp_set_alpha_operation (int alpha_operation, int alpha_type, int channel,
+	int apply_alpha, unsigned char alpha)
+{
+	gp3_cmd_header |= GP3_BLT_HDR_RASTER_ENABLE;
+	
+	/* THE AVAILABLE ALPHA DEFINITIONS FOLLOW THE HARDWARE       */
+	/* This allows us to avoid giant switch structures, but it   */
+	/* also implies that there is no mechanism to detect invalid */
+	/* parameters.                                               */
+
+	gp3_raster_mode = gp3_bpp | (unsigned long)alpha |
+		((unsigned long)apply_alpha     << 22) |
+		((unsigned long)alpha_operation << 20) |
+		((unsigned long)alpha_type      << 17) |
+		((unsigned long)channel         << 16);
+	
+	WRITE_COMMAND32 (GP3_BLT_RASTER_MODE, gp3_raster_mode);
+
+	/* CHECK IF DESTINATION IS REQUIRED */
+
+	if ( (alpha_operation == CIMGP_ALPHA_TIMES_A &&
+          channel == CIMGP_CHANNEL_A_SOURCE &&
+          alpha_type != CIMGP_CHANNEL_B_ALPHA &&
+          alpha_type != CIMGP_ALPHA_FROM_RGB_B)  ||
+         (alpha_operation == CIMGP_BETA_TIMES_B &&
+          channel == CIMGP_CHANNEL_A_DEST &&
+          alpha_type != CIMGP_CHANNEL_A_ALPHA &&
+          alpha_type != CIMGP_ALPHA_FROM_RGB_A))
+    {
+        gp3_blt_mode = 0;
+    }
+    else
+        gp3_blt_mode = GP3_BM_DST_REQ;
+}
+
+/*---------------------------------------------------------------------------
+ * gp_set_solid_pattern
+ *
+ * This routine is called to program the hardware for a solid pattern.  It need
+ * not be called for any other reason.  As a side effect, this routine will
+ * clear any 8x8 pattern data.
+ *-------------------------------------------------------------------------*/
+
+void gp_set_solid_pattern (unsigned long color)
+{
+	/* CHANNEL 3 IS NOT NEEDED FOR SOLID PATTERNS */
+
+	gp3_ch3_pat = 0;
+
+	/* SET SOLID PATTERN IN COMMAND BUFFER */
+	/* We are assuming that only one pattern type is ever set for a */
+	/* BLT.  We are also assuming that gp_set_raster_operation will */
+	/* be called before this routine.  With these assumptions, we   */
+	/* will thus never have to change the raster mode register for  */
+	/* solid patterns.                                              */
+
+	if (gp3_blt)
+	{
+		gp3_cmd_header |= GP3_BLT_HDR_PAT_CLR0_ENABLE;
+
+		WRITE_COMMAND32 (GP3_BLT_PAT_COLOR_0, color);
+	}
+	else
+	{
+		gp3_cmd_header |= GP3_VEC_HDR_PAT_CLR0_ENABLE;
+
+		WRITE_COMMAND32 (GP3_VECTOR_PAT_COLOR_0, color);
+	}
+}
+
+/*---------------------------------------------------------------------------
+ * gp_set_mono_pattern
+ *
+ * This routine is called to program the hardware for a monochrome pattern.
+ * As a side effect, this routine will clear any 8x8 pattern data.
+ *-------------------------------------------------------------------------*/
+
+void gp_set_mono_pattern (unsigned long bgcolor, unsigned long fgcolor,
+	unsigned long data0, unsigned long data1, int transparent, int x, int y)
+{
+	/* CHANNEL 3 IS NOT NEEDED FOR MONOCHROME PATTERNS */
+
+	gp3_ch3_pat = 0;
+
+	/* UPDATE RASTER MODE REGISTER */
+
+	if (transparent) gp3_raster_mode |= GP3_RM_PAT_MONO | GP3_RM_PAT_TRANS;
+	else             gp3_raster_mode |= GP3_RM_PAT_MONO;
+		
+	gp3_cmd_header |= GP3_BLT_HDR_RASTER_ENABLE;
+
+	WRITE_COMMAND32 (GP3_BLT_RASTER_MODE, gp3_raster_mode);	
+
+	/* SET MONOCHROME PATTERN DATA AND COLORS */
+
+	if (gp3_blt)
+	{
+		gp3_cmd_header |= (GP3_BLT_HDR_PAT_CLR0_ENABLE | GP3_BLT_HDR_PAT_CLR1_ENABLE |
+			GP3_BLT_HDR_PAT_DATA0_ENABLE | GP3_BLT_HDR_PAT_DATA1_ENABLE);
+
+		WRITE_COMMAND32 (GP3_BLT_PAT_COLOR_0, bgcolor);
+		WRITE_COMMAND32 (GP3_BLT_PAT_COLOR_1, fgcolor);
+		WRITE_COMMAND32 (GP3_BLT_PAT_DATA_0,  data0);
+		WRITE_COMMAND32 (GP3_BLT_PAT_DATA_1,  data1);
+	}
+	else
+	{
+		gp3_cmd_header |= (GP3_VEC_HDR_PAT_CLR0_ENABLE | GP3_VEC_HDR_PAT_CLR1_ENABLE |
+			GP3_VEC_HDR_PAT_DATA0_ENABLE | GP3_VEC_HDR_PAT_DATA1_ENABLE);
+
+		WRITE_COMMAND32 (GP3_VECTOR_PAT_COLOR_0, bgcolor);
+		WRITE_COMMAND32 (GP3_VECTOR_PAT_COLOR_1, fgcolor);
+		WRITE_COMMAND32 (GP3_VECTOR_PAT_DATA_0,  data0);
+		WRITE_COMMAND32 (GP3_VECTOR_PAT_DATA_1,  data1);
+	}
+
+	/* SAVE PATTERN ORIGIN */
+
+	gp3_pat_origin = ((unsigned long)y << 29) | (((unsigned long)x & 7) << 26);
+}
+
+/*---------------------------------------------------------------------------
+ * gp_set_pattern_origin
+ *
+ * This routine overrides the pattern origins set in gp_set_mono_pattern or
+ * gp_set_color_pattern.  It is generally used to override the original
+ * pattern origin due to a change in clipping.
+ *-------------------------------------------------------------------------*/
+
+void gp_set_pattern_origin (int x, int y)
+{
+	/* SAVE PATTERN ORIGIN */
+
+	gp3_pat_origin = ((unsigned long)y << 29) | (((unsigned long)x & 7) << 26);
+}
+
+/*---------------------------------------------------------------------------
+ * gp_set_color_pattern
+ *
+ * This routine is called to program a 8x8 color pattern into the LUT hardware.
+ * Unlike the other pattern routines, this routine must be called before
+ * any gp_declare_xxxx routines.  The pattern that is programmed into the
+ * hardware will stay persistent for all subsequent primitives until one of
+ * the following conditions happens.
+ *   - Another pattern type is programmed.
+ *   - A color-conversion BLT rotation BLT.
+ *-------------------------------------------------------------------------*/
+
+void gp_set_color_pattern (unsigned long *pattern, int format, int x, int y)
+{
+	unsigned long size_dwords, temp;
+	
+	gp3_ch3_pat = 1;
+
+	/* SAVE COLOR PATTERN SOURCE INFO */
+	/* Color patterns can be in a format different than the primary display. */
+	/* 4BPP patterns are not supported.                                      */
+	
+	gp3_pat_pix_shift = (unsigned long)((format >> 2) & 3);
+	gp3_pat_format = (((unsigned long)format & 0xF)  << 24) |
+		             (((unsigned long)format & 0x10) << 17) |
+					 GP3_CH3_COLOR_PAT_ENABLE               |
+					 GP3_CH3_C3EN;
+
+	size_dwords = (64 << gp3_pat_pix_shift) >> 2;
+
+	/* CHECK FOR WRAP AFTER LUT LOAD                 */
+	/* Primitive size is 12 plus the amount of data. */
+
+	gp3_cmd_next = gp3_cmd_current + (size_dwords << 2) + 12;
+	
+	if ((gp3_cmd_bottom - gp3_cmd_next) <= GP3_MAX_COMMAND_SIZE)
+	{
+		gp3_cmd_next   = gp3_cmd_top;
+		gp3_cmd_header = GP3_LUT_HDR_TYPE | GP3_LUT_HDR_WRAP | GP3_LUT_HDR_DATA_ENABLE;
+
+		/* WAIT FOR HARDWARE           */
+		/* Same logic as BLT wrapping. */
+
+		GP3_WAIT_WRAP(temp);
+	}
+	else
+	{
+		gp3_cmd_header = GP3_LUT_HDR_TYPE | GP3_LUT_HDR_DATA_ENABLE;
+
+		/* WAIT FOR AVAILABLE SPACE */
+
+		GP3_WAIT_PRIMITIVE(temp);
+	}
+
+	/* SAVE CURRENT BUFFER POINTER */
+
+	cim_cmd_ptr = cim_cmd_base_ptr + gp3_cmd_current;
+
+	/* PREPARE FOR COMMAND BUFFER DATA WRITES                 */
+	/* Pattern data is contiguous DWORDs at LUT address 0x100 */
+
+	WRITE_COMMAND32 (0, gp3_cmd_header);
+	WRITE_COMMAND32 (4, 0x100);
+	WRITE_COMMAND32 (8, size_dwords | GP3_LUT_DATA_TYPE);	
+
+	/* WRITE ALL DATA */
+
+	WRITE_COMMAND_STRING32 (12, pattern, 0, size_dwords);
+
+	/* START OPERATION */
+
+	WRITE_GP32 (GP3_CMD_WRITE, gp3_cmd_next);
+	gp3_cmd_current = gp3_cmd_next;
+
+	/* SAVE PATTERN ORIGIN */
+
+	gp3_pat_origin = ((unsigned long)y << 29) | (((unsigned long)x & 7) << 26);
+}
+
+/*---------------------------------------------------------------------------
+ * gp_set_mono_source
+ *
+ * This routine is called to program the colors for monochrome source data.
+ *-------------------------------------------------------------------------*/
+
+void gp_set_mono_source (unsigned long bgcolor, unsigned long fgcolor,
+	int transparent)
+{
+	/* UPDATE RASTER MODE REGISTER IF TRANSPARENT */
+
+	if (transparent)
+	{
+		gp3_cmd_header  |= GP3_BLT_HDR_RASTER_ENABLE;
+		gp3_raster_mode |= GP3_RM_SRC_TRANS;
+
+		WRITE_COMMAND32 (GP3_BLT_RASTER_MODE, gp3_raster_mode);	
+	}
+
+	/* SET MONOCHROME SOURCE COLORS */
+	/* Note that this routine only sets the colors.  The actual */
+	/* source type is determined by the final output routine    */
+	/* (gp_mono_bitmap_xxx, gp_color_bitmap_xxx, etc.)          */
+
+	gp3_cmd_header |= GP3_BLT_HDR_SRC_FG_ENABLE | GP3_BLT_HDR_SRC_BG_ENABLE;
+
+	WRITE_COMMAND32 (GP3_BLT_SRC_COLOR_FG, fgcolor);
+	WRITE_COMMAND32 (GP3_BLT_SRC_COLOR_BG, bgcolor);
+}
+
+/*---------------------------------------------------------------------------
+ * gp_set_solid_source
+ *
+ * This routine is called to program a solid source color.  A solid source
+ * color is used primarily for vectors or antialiased text.
+ *-------------------------------------------------------------------------*/
+
+void gp_set_solid_source (unsigned long color)
+{
+	/* SET SOLID SOURCE COLOR */
+	/* The solid source register is in the same place for both BLTs and */
+	/* vectors.                                                         */
+
+	gp3_cmd_header |= GP3_BLT_HDR_SRC_FG_ENABLE;
+
+	WRITE_COMMAND32 (GP3_BLT_SRC_COLOR_FG, color);
+}
+
+/*---------------------------------------------------------------------------
+ * gp_set_source_transparency
+ *
+ * This routine sets the source transparency and mask to be used in future
+ * rendering operations.  Transparency is cleared by gp_set_raster_operation,
+ * so this routine should never be called first.
+ *-------------------------------------------------------------------------*/
+
+void gp_set_source_transparency (unsigned long color, unsigned long mask)
+{
+	gp3_raster_mode |= GP3_RM_SRC_TRANS;
+	gp3_cmd_header  |= GP3_BLT_HDR_RASTER_ENABLE | GP3_BLT_HDR_SRC_FG_ENABLE |
+		GP3_BLT_HDR_SRC_BG_ENABLE;
+	
+	WRITE_COMMAND32 (GP3_BLT_RASTER_MODE, gp3_raster_mode);	
+	WRITE_COMMAND32 (GP3_BLT_SRC_COLOR_FG, color);
+	WRITE_COMMAND32 (GP3_BLT_SRC_COLOR_BG, mask);
+}
+
+/*---------------------------------------------------------------------------
+ * gp_program_lut
+ *
+ * This routine is called to program the hardware LUT with color-conversion
+ * information.  This routine should be called before any gp_declare_xxxx
+ * routines.
+ *
+ * colors   - Pointer to an array of DWORDs for color expansion.
+ *
+ * full_lut - Selector between 4BPP and 8BPP expansion. The hardware is
+ *            initialized with 16 dwords for 4BPP expansion and 256 dwords
+ *            for 8BPP expansion.
+ *-------------------------------------------------------------------------*/
+
+void gp_program_lut (unsigned long *colors, int full_lut)
+{
+	unsigned long size_dwords, temp;
+	
+	/* SIZE IS EITHER 16 DWORDS (4BPP) or 256 DWORDS (8BPP) */
+
+	if (full_lut) size_dwords = 256;
+	else          size_dwords = 16;
+
+	/* CHECK FOR WRAP AFTER LUT LOAD                 */
+	/* Primitive size is 12 plus the amount of data. */
+
+	gp3_cmd_next = gp3_cmd_current + (size_dwords << 2) + 12;
+	
+	if ((gp3_cmd_bottom - gp3_cmd_next) <= GP3_MAX_COMMAND_SIZE)
+	{
+		gp3_cmd_next   = gp3_cmd_top;
+		gp3_cmd_header = GP3_LUT_HDR_TYPE | GP3_LUT_HDR_WRAP | GP3_LUT_HDR_DATA_ENABLE;
+
+		/* WAIT FOR HARDWARE           */
+		/* Same logic as BLT wrapping. */
+
+		GP3_WAIT_WRAP(temp);
+	}
+	else
+	{
+		gp3_cmd_header = GP3_LUT_HDR_TYPE | GP3_LUT_HDR_DATA_ENABLE;
+
+		/* WAIT FOR AVAILABLE SPACE */
+
+		GP3_WAIT_PRIMITIVE(temp);
+	}
+
+	/* SAVE CURRENT BUFFER POINTER */
+
+	cim_cmd_ptr = cim_cmd_base_ptr + gp3_cmd_current;
+
+	/* PREPARE FOR COMMAND BUFFER DATA WRITES             */
+	/* Pattern data is contiguous DWORDs at LUT address 0 */
+
+	WRITE_COMMAND32 (0, gp3_cmd_header);
+	WRITE_COMMAND32 (4, 0);
+	WRITE_COMMAND32 (8, (size_dwords | GP3_LUT_DATA_TYPE));	
+
+	/* WRITE ALL DATA */
+
+	WRITE_COMMAND_STRING32 (12, colors, 0, size_dwords);
+
+	/* START OPERATION */
+
+	WRITE_GP32 (GP3_CMD_WRITE, gp3_cmd_next);
+	gp3_cmd_current = gp3_cmd_next;
+}
+
+/*---------------------------------------------------------------------------
+ * gp_set_vector_pattern
+ *
+ * This routine is called to program the hardware LUT with a vector pattern.
+ * A vector pattern is programmed as a 32-bit mask that specifies a
+ * transparency pattern.  A length parameter is used to specify patterns
+ * smaller than 32.  Note that vectors in Geode LX do not continue across corners.
+ * The beginning of each vector will always begin with bit 0 of the vector
+ * pattern.  It is the responsibility of the caller to update the pattern
+ * if an alternate behavior is desired.
+ *
+ * This routine faces the same restrictions of all routines that program
+ * the LUT, in that it must be called before any gp_declare_xxxx routines,
+ * it cannot be combined with an 8x8 color pattern, color conversion or
+ * rotation.
+ *-------------------------------------------------------------------------*/
+
+void gp_set_vector_pattern (unsigned long pattern, unsigned long color, int length)
+{
+	unsigned long temp, mask;
+	
+	gp3_ch3_pat = 1;
+	gp3_vector_pattern_color = color;
+
+	/* CREATE SUITABLE PATTERN MASK */
+	/* The GP requires a minimum of four pixels in a vector pattern.  We */
+	/* can get around this restriction by doubling any patterns smaller  */
+	/* than 4 pixels.                                                    */
+
+	while (length < 4)
+	{
+		mask = 0xFFFFFFFF >> (32 - length);
+		pattern = (pattern << length) | (pattern & mask);
+		length <<= 1;
+	}
+	mask = 0xFFFFFFFF >> (32 - length);
+
+    gp3_vec_pat = pattern;
+
+	/* CHECK FOR WRAP AFTER LUT LOAD */
+
+	gp3_cmd_next = gp3_cmd_current + GP3_VECTOR_PATTERN_COMMAND_SIZE;
+	
+	if ((gp3_cmd_bottom - gp3_cmd_next) <= GP3_MAX_COMMAND_SIZE)
+	{
+		gp3_cmd_next   = gp3_cmd_top;
+		gp3_cmd_header = GP3_LUT_HDR_TYPE | GP3_LUT_HDR_WRAP | GP3_LUT_HDR_DATA_ENABLE;
+
+		/* WAIT FOR HARDWARE           */
+		/* Same logic as BLT wrapping. */
+
+		GP3_WAIT_WRAP(temp);
+	}
+	else
+	{
+		gp3_cmd_header = GP3_LUT_HDR_TYPE | GP3_LUT_HDR_DATA_ENABLE;
+
+		/* WAIT FOR AVAILABLE SPACE */
+
+		GP3_WAIT_PRIMITIVE(temp);
+	}
+
+	/* SAVE CURRENT BUFFER POINTER */
+
+	cim_cmd_ptr = cim_cmd_base_ptr + gp3_cmd_current;
+
+	/* PREPARE FOR COMMAND BUFFER DATA WRITES      */
+	/* Pattern data is 2 DWORDs at 0x100 and 0x101 */
+
+	WRITE_COMMAND32 (0, gp3_cmd_header);
+	WRITE_COMMAND32 (4, 0x100);
+	WRITE_COMMAND32 (8, (2 | GP3_LUT_DATA_TYPE));	
+	WRITE_COMMAND32 (12, pattern);
+	WRITE_COMMAND32 (16, mask);
+
+	/* START OPERATION */
+
+	WRITE_GP32 (GP3_CMD_WRITE, gp3_cmd_next);
+	gp3_cmd_current = gp3_cmd_next;
+}
+
+/*---------------------------------------------------------------------------
+ * gp_set_strides
+ *
+ * This routine is called to program the pitch between successive lines of
+ * data in the frame buffer.  The strides should be DWORD aligned and less
+ * than 64K.  These restrictions are not checked by the API.
+ *-------------------------------------------------------------------------*/
+
+void gp_set_strides (unsigned long dst_stride, unsigned long src_stride)
+{
+	/* SAVE STRIDES */
+	/* The source stride may be needed later for channel 3 source data and */
+	/* we may need to use these strides in calculations.                   */
+
+	gp3_src_stride = src_stride;
+	gp3_dst_stride = dst_stride;
+
+	/* ENABLE STRIDES */
+	/* The stride register is in the same place for BLTs and vectors */
+
+	gp3_cmd_header |= GP3_BLT_HDR_STRIDE_ENABLE;
+
+	WRITE_COMMAND32 (GP3_BLT_STRIDE, ((src_stride << 16) | dst_stride));	
+}
+
+/*---------------------------------------------------------------------------
+ * gp_set_source_format
+ *
+ * This routine is used to program the format of source data used in subsequent
+ * color-conversion or rotation operations.  Note that 4BPP indexed and 8BPP
+ * indexed source formats cannot be used when rotating, as the LUT will be
+ * destroyed.  These formats also cannot be combined with an 8x8 color pattern.
+ * The supported formats mirror the hardware and are described as follows:
+ *
+ * 0  - 8BPP 3:3:2
+ * 1  - 8BPP indexed
+ * 4  - 16BPP 4:4:4:4
+ * 5  - 16BPP 1:5:5:5
+ * 6  - 16BPP 5:6:5
+ * 7  - 16BPP YUV
+ * 8  - 32BPP 8:8:8:8
+ * 13 - 4BPP indexed
+ * 20 - 16BPP 4:4:4:4 BGR
+ * 21 - 16BPP 1:5:5:5 BGR
+ * 22 - 16BPP 0:5:6:5 BGR
+ * 24 - 32BPP 8:8:8:8 BGR
+ *-------------------------------------------------------------------------*/
+
+void gp_set_source_format (int format)
+{
+	/* SAVE FORMAT */
+	/* We will combine the source format later when doing color conversion. */
+	/* We also save the pixel size for host source calculations.            */
+	/* Conveniently, the source formats are organized such that the upper   */
+	/* two bits of the nibble represent the pixel shift, with a pixel shift */
+	/* of 3 being a special case for 4BPP data.  Clever, yes?  Even more    */
+	/* clever, bit 4 indicates BGR ordering.                                */
+
+	gp3_src_pix_shift = (unsigned long)((format >> 2) & 3);
+	gp3_src_format = (((unsigned long)format & 0xF)  << 24) |
+		             (((unsigned long)format & 0x10) << 18);
+}
+
+/*---------------------------------------------------------------------------
+ * gp_pattern_fill
+ *
+ * This routine is called to perform a simple pattern fill.  The pattern
+ * can be solid, monochrome or a preprogrammed 8x8 color pattern.  If
+ * the ROP involves source data, that source data will be constant.
+ *-------------------------------------------------------------------------*/
+
+void gp_pattern_fill (unsigned long dstoffset, unsigned long width, unsigned long height)
+{
+    unsigned long base_register;
+
+    base_register = (gp3_base_register & ~GP3_BASE_OFFSET_DSTMASK) |
+                   ((gp3_fb_base << 24) + (dstoffset & 0xFFC00000));
+
+    /* ENABLE RELEVANT REGISTERS */
+	/* Note that we always enable and write the channel 3 mode, if only */
+	/* to turn it off.   Cimarron also always writes the base offset    */
+	/* register to allow operation with frame buffers larger than 16MB. */
+
+	gp3_cmd_header |= GP3_BLT_HDR_DST_OFF_ENABLE     |
+		              GP3_BLT_HDR_WIDHI_ENABLE       |
+					  GP3_BLT_HDR_BASE_OFFSET_ENABLE |
+					  GP3_BLT_HDR_CH3_STR_ENABLE     |
+					  GP3_BLT_HDR_CH3_WIDHI_ENABLE   |
+					  GP3_BLT_HDR_BLT_MODE_ENABLE;
+
+	/* WRITE THE REGISTERS COMMON TO ALL PATTERN TYPES */
+	/* The destination base is the frame buffer base plus whatever */
+	/* 4MB segment we happen to be BLTing to.                      */
+
+	WRITE_COMMAND32 (GP3_BLT_WID_HEIGHT, ((width << 16) | height));
+	WRITE_COMMAND32 (GP3_BLT_BASE_OFFSET, base_register);
+	
+	/* CHECK 8X8 COLOR PATTERN CASE */
+
+	if (gp3_ch3_pat)
+	{
+		/* SET CHANNEL 3 PATTERN ORIGINS */
+
+		gp3_cmd_header |= GP3_BLT_HDR_CH3_OFF_ENABLE;
+
+		/* INITIALIZE CHANNEL 3 PARAMETERS */
+
+		WRITE_COMMAND32 (GP3_BLT_CH3_WIDHI, ((width << 16) | height));
+		WRITE_COMMAND32 (GP3_BLT_CH3_OFFSET, gp3_pat_origin);
+		WRITE_COMMAND32 (GP3_BLT_DST_OFFSET, dstoffset & 0x3FFFFF);
+		WRITE_COMMAND32 (GP3_BLT_CH3_MODE_STR, gp3_pat_format);
+	}
+	else
+	{
+		/* DISABLE CHANNEL 3 AND USE NORMAL PATTERN ORIGINS */
+
+		WRITE_COMMAND32 (GP3_BLT_CH3_MODE_STR, 0);
+		WRITE_COMMAND32 (GP3_BLT_DST_OFFSET, ((dstoffset & 0x3FFFFF) | gp3_pat_origin));
+	}
+	
+	/* START THE BLT */
+
+	WRITE_COMMAND32 (GP3_BLT_CMD_HEADER, gp3_cmd_header);
+	WRITE_COMMAND32 (GP3_BLT_MODE, gp3_blt_mode);
+	WRITE_GP32 (GP3_CMD_WRITE, gp3_cmd_next);
+	gp3_cmd_current = gp3_cmd_next;
+}
+
+/*---------------------------------------------------------------------------
+ * gp_screen_to_screen_blt
+ *
+ * This routine is called to perform a BLT from one location inside video
+ * memory to another location inside video memory.  The source and destination
+ * formats are assumed to be the current BPP.  Whenever possible, this routine
+ * tries to use channel 3 to fetch source data.  The BLT flags can affect this
+ * behavior in the following ways:
+ *   CIMGP_BLTFLAGS_PRES_COLOR_PAT
+ *      A color pattern is being stored in the channel 3 buffer.  It is either
+ *      being stored for a later BLT or being combined with the current source
+ *      data.  Channel 3 cannot be used to fetch source data or the pattern
+ *      will be overwritten.
+ *   CIMGP_BLTFLAGS_PRES_LUT
+ *      If the first flag is not set, this flag will limit the use of the
+ *      channel 3 buffer to 1K.
+ *-------------------------------------------------------------------------*/
+
+void gp_screen_to_screen_blt (unsigned long dstoffset, unsigned long srcoffset,
+	unsigned long width, unsigned long height, int flags)
+{
+	unsigned long base;
+	unsigned long ch3_flags = 0;
+	unsigned long blt_mode  = gp3_blt_mode;
+	unsigned long size = ((width << 16) | height);
+    unsigned long dstbase, srcbase;
+
+    /* CALCULATE BASE OFFSETS                                             */
+    /* We need to set the 4MB aligned base offsets before we add offsets  */
+    /* for negative BLTs.                                                 */
+
+    srcbase = srcoffset & 0xFFC00000;
+    dstbase = dstoffset & 0xFFC00000;
+    srcoffset &= 0x3FFFFF;
+    dstoffset &= 0x3FFFFF;
+
+    /* ADJUST OFFSETS BASED ON FLAGS */
+	/* We adjust the source and destination offsets to point to the first */
+	/* byte of the first pixel of the BLT.  This routine assumes that the */
+	/* source and destination regions do not wrap past the end of a 16MB  */
+	/* region.                                                            */
+
+	if (flags & CIMGP_NEGXDIR)
+	{
+		srcoffset += (width << gp3_pix_shift) - 1;
+		dstoffset += (width << gp3_pix_shift) - 1;
+		blt_mode  |= GP3_BM_NEG_XDIR;
+		ch3_flags |= GP3_CH3_NEG_XDIR;
+	}
+	if (flags & CIMGP_NEGYDIR)
+	{
+		srcoffset += (height - 1) * gp3_src_stride;
+		dstoffset += (height - 1) * gp3_dst_stride;
+		blt_mode  |= GP3_BM_NEG_YDIR;
+		ch3_flags |= GP3_CH3_NEG_YDIR;
+	}
+	
+	/* BRANCH BASED ON CHANNEL 3                                     */
+	/* If a color pattern is not being saved or used, channel 3 will */
+	/* be used to fetch source for maximum throughput.   Channel 3   */
+    /* is not used if transparency or alpha blending is enabled.     */
+
+	if (!(gp3_blt_flags & CIMGP_BLTFLAGS_PRES_COLOR_PAT) &&
+        !(gp3_raster_mode & GP3_RM_SRC_TRANS) &&
+        !(flags & CIMGP_NEGYDIR))
+	{
+		base = ((gp3_fb_base << 24) +  dstbase)        |
+		       ((gp3_fb_base << 4)  + (srcbase >> 20)) |
+                (gp3_base_register & GP3_BASE_OFFSET_SRCMASK);
+
+		gp3_cmd_header |= GP3_BLT_HDR_DST_OFF_ENABLE     |
+						  GP3_BLT_HDR_WIDHI_ENABLE       |
+						  GP3_BLT_HDR_CH3_STR_ENABLE     |
+						  GP3_BLT_HDR_CH3_WIDHI_ENABLE   |
+						  GP3_BLT_HDR_CH3_OFF_ENABLE     |
+						  GP3_BLT_HDR_BASE_OFFSET_ENABLE |
+						  GP3_BLT_HDR_BLT_MODE_ENABLE;
+
+		WRITE_COMMAND32 (GP3_BLT_DST_OFFSET, (dstoffset | gp3_pat_origin));
+		WRITE_COMMAND32 (GP3_BLT_CH3_OFFSET, srcoffset);
+		WRITE_COMMAND32 (GP3_BLT_WID_HEIGHT, size);
+		WRITE_COMMAND32 (GP3_BLT_CH3_WIDHI, size);
+		WRITE_COMMAND32 (GP3_BLT_BASE_OFFSET, base);
+		WRITE_COMMAND32 (GP3_BLT_CH3_MODE_STR,
+			  GP3_CH3_C3EN                                    |
+			  GP3_CH3_REPLACE_SOURCE                          |
+			  gp3_ch3_bpp                                     |
+			  gp3_src_stride                                  |
+			  ch3_flags                                       |
+			((gp3_blt_flags & CIMGP_ENABLE_PREFETCH)   << 17) |
+			((gp3_blt_flags & CIMGP_BLTFLAGS_PRES_LUT) << 20));
+	}
+	else
+	{
+		/* CALCULATE BASE OFFSET REGISTER */
+
+		base = ((gp3_fb_base << 24) +  dstbase)        |
+		       ((gp3_fb_base << 14) + (srcbase >> 10)) |
+               (gp3_base_register & GP3_BASE_OFFSET_CH3MASK);
+
+		/* PROGRAM THE NORMAL SOURCE CHANNEL REGISTERS                */
+		/* We assume that a color pattern is being ROPed with source  */
+		/* data if the pattern type is color and the preserve pattern */
+		/* was set.                                                   */
+
+		blt_mode |= GP3_BM_SRC_FB;
+
+		gp3_cmd_header |= GP3_BLT_HDR_SRC_OFF_ENABLE     |
+			              GP3_BLT_HDR_DST_OFF_ENABLE     |
+						  GP3_BLT_HDR_WIDHI_ENABLE       |
+                          GP3_BLT_HDR_CH3_WIDHI_ENABLE   |
+						  GP3_BLT_HDR_CH3_STR_ENABLE     |
+                          GP3_BLT_HDR_CH3_OFF_ENABLE     |
+						  GP3_BLT_HDR_BASE_OFFSET_ENABLE |
+						  GP3_BLT_HDR_BLT_MODE_ENABLE;
+
+		if (gp3_ch3_pat)
+		{
+			WRITE_COMMAND32 (GP3_BLT_CH3_OFFSET, gp3_pat_origin);
+			WRITE_COMMAND32 (GP3_BLT_DST_OFFSET, dstoffset);
+			WRITE_COMMAND32 (GP3_BLT_CH3_MODE_STR, gp3_pat_format | ch3_flags);
+            WRITE_COMMAND32 (GP3_BLT_CH3_WIDHI, size);
+		}
+		else
+		{
+			WRITE_COMMAND32 (GP3_BLT_DST_OFFSET, dstoffset | gp3_pat_origin);
+			WRITE_COMMAND32 (GP3_BLT_CH3_MODE_STR, 0);
+		}
+		
+		WRITE_COMMAND32 (GP3_BLT_SRC_OFFSET, srcoffset);
+		WRITE_COMMAND32 (GP3_BLT_WID_HEIGHT, size);
+		WRITE_COMMAND32 (GP3_BLT_BASE_OFFSET, base);
+	}
+		
+	/* START THE BLT */
+
+	WRITE_COMMAND32 (GP3_BLT_CMD_HEADER, gp3_cmd_header);
+	WRITE_COMMAND32 (GP3_BLT_MODE, blt_mode);
+	WRITE_GP32 (GP3_CMD_WRITE, gp3_cmd_next);
+	gp3_cmd_current = gp3_cmd_next;
+}
+
+/*---------------------------------------------------------------------------
+ * gp_screen_to_screen_convert
+ *
+ * This routine is called to color-convert a rectangular region of the frame
+ * buffer into the current BPP. The format of the source region is programmed
+ * by gp_set_source_format.
+ *-------------------------------------------------------------------------*/
+
+void gp_screen_to_screen_convert (unsigned long dstoffset, unsigned long srcoffset,
+    unsigned long width, unsigned long height, int nibble)
+{
+	unsigned long size = ((width << 16) | height);
+	unsigned long ch3_offset = srcoffset & 0x3FFFFF;
+    unsigned long ch3_size, base;
+
+    base =  ((gp3_fb_base << 24) +  (dstoffset & 0xFFC00000))        |
+	        ((gp3_fb_base << 4)  + ((srcoffset & 0xFFC00000) >> 20)) |
+             (gp3_base_register & GP3_BASE_OFFSET_SRCMASK);
+
+	/* SET NIBBLE FOR 4BPP */
+	/* 4BPP is a special case in that it requires subpixel addressing.  The */
+	/* user must supply this information via the nibble parameter.  This    */
+	/* parameter is ignored for every other source format.                  */
+
+    ch3_size = size;
+	if (gp3_src_pix_shift == 3)
+		ch3_offset |= ((nibble & 1) << 25);
+    else if ((gp3_src_format & GP3_CH3_SRC_MASK) == GP3_CH3_SRC_24BPP_PACKED)
+        ch3_size = ((((width * 3) + 3) >> 2) << 16) | height;
+
+	/* SET APPROPRIATE ENABLES */
+
+	gp3_cmd_header |= GP3_BLT_HDR_DST_OFF_ENABLE     |
+		              GP3_BLT_HDR_WIDHI_ENABLE       |
+					  GP3_BLT_HDR_CH3_OFF_ENABLE     |
+					  GP3_BLT_HDR_CH3_STR_ENABLE     |
+					  GP3_BLT_HDR_CH3_WIDHI_ENABLE   |
+					  GP3_BLT_HDR_BASE_OFFSET_ENABLE |
+					  GP3_BLT_HDR_BLT_MODE_ENABLE;
+
+	/* WRITE ALL BLT REGISTERS */
+	
+	WRITE_COMMAND32 (GP3_BLT_DST_OFFSET, (dstoffset & 0x3FFFFF) | gp3_pat_origin);
+	WRITE_COMMAND32 (GP3_BLT_WID_HEIGHT, size);
+	WRITE_COMMAND32 (GP3_BLT_CH3_WIDHI, ch3_size);
+	WRITE_COMMAND32 (GP3_BLT_CH3_OFFSET, ch3_offset);
+	WRITE_COMMAND32 (GP3_BLT_CH3_MODE_STR,
+		GP3_CH3_C3EN                                    |
+		GP3_CH3_REPLACE_SOURCE                          |
+		gp3_src_format                                  |
+	  ((gp3_blt_flags & CIMGP_BLTFLAGS_PRES_LUT) << 20) |
+	  ((gp3_blt_flags & CIMGP_ENABLE_PREFETCH)   << 17) |
+	    gp3_src_stride);
+	WRITE_COMMAND32 (GP3_BLT_BASE_OFFSET, base);
+		
+	/* START THE BLT */
+
+    WRITE_COMMAND32 (GP3_BLT_CMD_HEADER, gp3_cmd_header);
+	WRITE_COMMAND32 (GP3_BLT_MODE, gp3_blt_mode);
+	WRITE_GP32 (GP3_CMD_WRITE, gp3_cmd_next);
+	gp3_cmd_current = gp3_cmd_next;
+}
+
+/*---------------------------------------------------------------------------
+ * gp_color_bitmap_to_screen_blt
+ *
+ * This routine is called to BLT data from system memory into the frame buffer.
+ * 'srcy' is deliberately omitted to prevent extra calculations for simple
+ * applications that have no source indexes.
+ *-------------------------------------------------------------------------*/
+
+void gp_color_bitmap_to_screen_blt (unsigned long dstoffset, unsigned long srcx,
+    unsigned long width, unsigned long height, unsigned char *data, long pitch)
+{
+	unsigned long indent, temp;
+	unsigned long total_dwords, size_dwords;
+	unsigned long dword_count, byte_count;
+	unsigned long size = ((width << 16) | height);
+	unsigned long srcoffset;
+		
+	/* ASSUME BITMAPS ARE DWORD ALIGNED */
+	/* We will offset into the source data in DWORD increments.  We */
+	/* set the source index to the remaining byte offset and        */
+	/* increment the size of each line to account for the dont-care */
+	/* pixel(s).                                                    */
+
+	indent    = srcx << gp3_pix_shift;
+	srcoffset = (indent & ~3L);
+	indent   &= 3;
+
+	/* PROGRAM THE NORMAL SOURCE CHANNEL REGISTERS                */
+	/* We assume that a color pattern is being ROPed with source  */
+	/* data if the pattern type is color and the preserve pattern */
+	/* was set.                                                   */
+
+	gp3_cmd_header |= GP3_BLT_HDR_SRC_OFF_ENABLE     |
+		              GP3_BLT_HDR_DST_OFF_ENABLE     |
+					  GP3_BLT_HDR_WIDHI_ENABLE       |
+					  GP3_BLT_HDR_CH3_STR_ENABLE     |
+					  GP3_BLT_HDR_BASE_OFFSET_ENABLE |
+					  GP3_BLT_HDR_BLT_MODE_ENABLE;
+
+	if (gp3_ch3_pat)
+	{
+		gp3_cmd_header |= GP3_BLT_HDR_CH3_OFF_ENABLE | GP3_BLT_HDR_CH3_WIDHI_ENABLE;
+
+		WRITE_COMMAND32 (GP3_BLT_CH3_OFFSET, gp3_pat_origin);
+		WRITE_COMMAND32 (GP3_BLT_DST_OFFSET, (dstoffset & 0x3FFFFF));
+		WRITE_COMMAND32 (GP3_BLT_CH3_MODE_STR, gp3_pat_format);
+        WRITE_COMMAND32 (GP3_BLT_CH3_WIDHI, size);
+	}
+	else
+	{
+		WRITE_COMMAND32 (GP3_BLT_DST_OFFSET, ((dstoffset & 0x3FFFFF) | gp3_pat_origin));
+		WRITE_COMMAND32 (GP3_BLT_CH3_MODE_STR, 0);
+	}
+	
+	WRITE_COMMAND32 (GP3_BLT_SRC_OFFSET, indent);
+	WRITE_COMMAND32 (GP3_BLT_WID_HEIGHT, size);
+	WRITE_COMMAND32 (GP3_BLT_BASE_OFFSET,
+		((gp3_fb_base << 24) + (dstoffset & 0xFFC00000)));
+	WRITE_COMMAND32 (GP3_BLT_MODE, gp3_blt_mode | GP3_BM_SRC_HOST);
+		
+	/* START THE BLT */
+
+	WRITE_COMMAND32 (GP3_BLT_CMD_HEADER, gp3_cmd_header);
+	WRITE_GP32 (GP3_CMD_WRITE, gp3_cmd_next);
+	gp3_cmd_current = gp3_cmd_next;
+
+	/* CALCULATE THE SIZE OF ONE LINE */
+
+	size = (width << gp3_pix_shift) + indent;
+	total_dwords = (size + 3) >> 2;
+	size_dwords  = (total_dwords << 2) + 8;
+	dword_count  = (size >> 2);
+	byte_count   = (size & 3);
+
+    /* CHECK FOR SMALL BLT CASE */
+
+    if (((total_dwords << 2) * height) <= GP3_BLT_1PASS_SIZE &&
+        (gp3_cmd_bottom - gp3_cmd_current) > (GP3_BLT_1PASS_SIZE + 72))
+    {
+        /* UPDATE THE COMMAND POINTER */
+
+		cim_cmd_ptr = cim_cmd_base_ptr + gp3_cmd_current;
+
+        /* CHECK IF A WRAP WILL BE NEEDED */
+
+		gp3_cmd_next = gp3_cmd_current + ((total_dwords << 2) * height) + 8;
+
+	    if ((gp3_cmd_bottom - gp3_cmd_next) <= GP3_MAX_COMMAND_SIZE)
+		{
+			gp3_cmd_next  = gp3_cmd_top;
+            	
+			GP3_WAIT_WRAP(temp);
+			WRITE_COMMAND32 (0, GP3_DATA_LOAD_HDR_TYPE | GP3_DATA_LOAD_HDR_WRAP |
+				GP3_DATA_LOAD_HDR_ENABLE);
+		}
+		else
+		{
+			GP3_WAIT_PRIMITIVE(temp);
+			WRITE_COMMAND32 (0, GP3_DATA_LOAD_HDR_TYPE | GP3_DATA_LOAD_HDR_ENABLE);
+		}
+
+        /* WRITE DWORD COUNT */
+
+		WRITE_COMMAND32 (4, GP3_HOST_SOURCE_TYPE | (total_dwords * height));
+
+        while (height--)
+	    {
+		    /* WRITE DATA */
+
+		    WRITE_COMMAND_STRING32 (8, data, srcoffset, dword_count);
+		    WRITE_COMMAND_STRING8 (8 + (dword_count << 2), data,
+			    srcoffset + (dword_count << 2), byte_count);
+
+		    srcoffset += pitch;
+            cim_cmd_ptr += total_dwords << 2;
+	    }
+
+        WRITE_GP32 (GP3_CMD_WRITE, gp3_cmd_next);
+		gp3_cmd_current = gp3_cmd_next;
+    }
+    else
+    {
+	    /* WRITE DATA LINE BY LINE */
+	    /* Each line will be created as a separate command buffer entry to allow */
+	    /* line-by-line wrapping and to allow simultaneous rendering by the HW.  */
+    	
+	    while (height--)
+	    {
+		    /* UPDATE THE COMMAND POINTER */
+		    /* The WRITE_COMMANDXX macros use a pointer to the current buffer space. */
+		    /* This is created by adding gp3_cmd_current to the base pointer.        */
+
+		    cim_cmd_ptr = cim_cmd_base_ptr + gp3_cmd_current;
+
+		    /* CHECK IF A WRAP WILL BE NEEDED */
+
+		    gp3_cmd_next = gp3_cmd_current + size_dwords;
+		    if ((gp3_cmd_bottom - gp3_cmd_next) <= GP3_MAX_COMMAND_SIZE)
+		    {
+			    gp3_cmd_next  = gp3_cmd_top;
+    			
+			    /* WAIT FOR HARDWARE */
+    			
+			    GP3_WAIT_WRAP(temp);
+			    WRITE_COMMAND32 (0, GP3_DATA_LOAD_HDR_TYPE | GP3_DATA_LOAD_HDR_WRAP |
+				    GP3_DATA_LOAD_HDR_ENABLE);
+		    }
+		    else
+		    {
+			    /* WAIT FOR AVAILABLE SPACE */
+
+			    GP3_WAIT_PRIMITIVE(temp);
+			    WRITE_COMMAND32 (0, GP3_DATA_LOAD_HDR_TYPE | GP3_DATA_LOAD_HDR_ENABLE);
+		    }
+
+		    /* WRITE DWORD COUNT */
+    		
+		    WRITE_COMMAND32 (4, GP3_HOST_SOURCE_TYPE | total_dwords);
+
+		    /* WRITE DATA */
+
+		    WRITE_COMMAND_STRING32 (8, data, srcoffset, dword_count);
+		    WRITE_COMMAND_STRING8 (8 + (dword_count << 2), data,
+			    srcoffset + (dword_count << 2), byte_count);
+
+		    /* UPDATE POINTERS */
+
+		    srcoffset += pitch;
+		    WRITE_GP32 (GP3_CMD_WRITE, gp3_cmd_next);
+		    gp3_cmd_current = gp3_cmd_next;
+	    }
+    }
+}
+
+/*---------------------------------------------------------------------------
+ * gp_color_convert_blt
+ *
+ * This routine is called to convert data that is stored in system memory
+ * into the current graphics BPP.  The source format is programmed in
+ * gp_set_source_format.
+ *-------------------------------------------------------------------------*/
+
+void gp_color_convert_blt (unsigned long dstoffset, unsigned long srcx,
+    unsigned long width, unsigned long height, unsigned char *data, long pitch)
+{
+	unsigned long indent, temp;
+	unsigned long total_dwords, size_dwords;
+	unsigned long dword_count, byte_count;
+	unsigned long size = ((width << 16) | height);
+    unsigned long ch3_size;
+	unsigned long ch3_offset, srcoffset;
+    unsigned long base;
+		
+	/* ASSUME BITMAPS ARE DWORD ALIGNED */
+	/* We will offset into the source data in DWORD increments.  We  */
+	/* set the source index to the remaining byte offset and         */
+	/* increment the size of each line to account for the dont-care  */
+	/* pixel(s).   For 4BPP source data, we also set the appropriate */
+	/* nibble index.                                                 */
+	
+    /* CALCULATE THE SIZE OF ONE LINE */
+
+    if ((gp3_src_format & GP3_CH3_SRC_MASK) == GP3_CH3_SRC_24BPP_PACKED)
+    {
+        /* HANDLE 24BPP */
+        /* Note that we do not do anything to guarantee that the source data        */
+        /* is DWORD aligned.  The logic here is that the source data will be        */
+        /* cacheable, in which case Geode LX will not lose any clocks for unaligned */
+        /* moves.  Also note that the channel 3 width is programmed as the          */
+        /* number of dwords, while the normal width is programmed as the number     */
+        /* of pixels.                                                               */
+
+        srcoffset  = srcx * 3;
+        ch3_offset = 0;
+        temp       = width * 3;
+        ch3_size   = (((temp + 3) >> 2) << 16) | height;
+    }
+    else
+    {
+        ch3_size = size;
+
+	    if (gp3_src_pix_shift == 3)
+	    {
+		    /* CALCULATE INDENT AND SOURCE OFFSET */
+
+		    indent     = (srcx >> 1);
+		    srcoffset  = (indent & ~3L);
+		    indent    &= 3;
+		    ch3_offset = indent | ((srcx & 1) << 25);
+
+		    temp = ((width + (srcx & 1) + 1) >> 1) + indent;
+	    }
+	    else
+	    {
+		    indent     = (srcx << gp3_src_pix_shift);
+		    srcoffset  = (indent & ~3L);
+		    indent    &= 3;
+		    ch3_offset = indent;
+
+		    temp = (width << gp3_src_pix_shift) + indent;
+	    }
+    }
+
+	total_dwords = (temp + 3) >> 2;
+	size_dwords  = (total_dwords << 2) + 8;
+	dword_count  = (temp >> 2);
+	byte_count   = (temp & 3);
+
+    base = ((gp3_fb_base << 24) + (dstoffset & 0xFFC00000)) |
+            (gp3_base_register & ~GP3_BASE_OFFSET_DSTMASK);
+
+	/* SET APPROPRIATE ENABLES */
+
+	gp3_cmd_header |= GP3_BLT_HDR_DST_OFF_ENABLE     |
+					  GP3_BLT_HDR_WIDHI_ENABLE       |
+					  GP3_BLT_HDR_CH3_STR_ENABLE     |
+					  GP3_BLT_HDR_CH3_OFF_ENABLE     |
+					  GP3_BLT_HDR_CH3_WIDHI_ENABLE   |
+					  GP3_BLT_HDR_BASE_OFFSET_ENABLE |
+					  GP3_BLT_HDR_BLT_MODE_ENABLE;
+
+	WRITE_COMMAND32 (GP3_BLT_DST_OFFSET, (dstoffset & 0x3FFFFF) | gp3_pat_origin);
+	WRITE_COMMAND32 (GP3_BLT_CH3_OFFSET, ch3_offset);
+	WRITE_COMMAND32 (GP3_BLT_WID_HEIGHT, size);
+	WRITE_COMMAND32 (GP3_BLT_CH3_WIDHI, ch3_size);
+	WRITE_COMMAND32 (GP3_BLT_BASE_OFFSET, base);
+	WRITE_COMMAND32 (GP3_BLT_CH3_MODE_STR,
+		GP3_CH3_C3EN           |
+		GP3_CH3_REPLACE_SOURCE |
+		GP3_CH3_HST_SRC_ENABLE |
+		gp3_src_format         |
+	  ((gp3_blt_flags & CIMGP_BLTFLAGS_PRES_LUT) << 20));
+	WRITE_COMMAND32 (GP3_BLT_MODE, gp3_blt_mode);
+
+	/* START THE BLT */
+
+	WRITE_COMMAND32 (GP3_BLT_CMD_HEADER, gp3_cmd_header);
+	WRITE_GP32 (GP3_CMD_WRITE, gp3_cmd_next);
+	gp3_cmd_current = gp3_cmd_next;
+
+    if (((total_dwords << 2) * height) <= GP3_BLT_1PASS_SIZE &&
+        (gp3_cmd_bottom - gp3_cmd_current) > (GP3_BLT_1PASS_SIZE + 72))
+    {
+        /* UPDATE THE COMMAND POINTER */
+
+		cim_cmd_ptr = cim_cmd_base_ptr + gp3_cmd_current;
+
+        /* CHECK IF A WRAP WILL BE NEEDED */
+
+		gp3_cmd_next = gp3_cmd_current + ((total_dwords << 2) * height) + 8;
+
+	    if ((gp3_cmd_bottom - gp3_cmd_next) <= GP3_MAX_COMMAND_SIZE)
+		{
+			gp3_cmd_next  = gp3_cmd_top;
+            	
+			GP3_WAIT_WRAP(temp);
+			WRITE_COMMAND32 (0, GP3_DATA_LOAD_HDR_TYPE | GP3_DATA_LOAD_HDR_WRAP |
+				GP3_DATA_LOAD_HDR_ENABLE);
+		}
+		else
+		{
+			GP3_WAIT_PRIMITIVE(temp);
+			WRITE_COMMAND32 (0, GP3_DATA_LOAD_HDR_TYPE | GP3_DATA_LOAD_HDR_ENABLE);
+		}
+
+        /* WRITE DWORD COUNT */
+
+		WRITE_COMMAND32 (4, GP3_CH3_HOST_SOURCE_TYPE | (total_dwords * height));
+
+        while (height--)
+	    {
+		    /* WRITE DATA */
+
+		    WRITE_COMMAND_STRING32 (8, data, srcoffset, dword_count);
+		    WRITE_COMMAND_STRING8 (8 + (dword_count << 2), data,
+			    srcoffset + (dword_count << 2), byte_count);
+
+		    srcoffset += pitch;
+            cim_cmd_ptr += total_dwords << 2;
+	    }
+
+        WRITE_GP32 (GP3_CMD_WRITE, gp3_cmd_next);
+		gp3_cmd_current = gp3_cmd_next;
+    }
+    else
+    {
+	    /* WRITE DATA LINE BY LINE */
+	    /* Each line will be created as a separate command buffer entry to allow */
+	    /* line-by-line wrapping and to allow simultaneous rendering by the HW.  */
+    	
+	    while (height--)
+	    {
+		    /* UPDATE THE COMMAND POINTER */
+		    /* The WRITE_COMMANDXX macros use a pointer to the current buffer space. */
+		    /* This is created by adding gp3_cmd_current to the base pointer.        */
+
+		    cim_cmd_ptr = cim_cmd_base_ptr + gp3_cmd_current;
+
+		    /* CHECK IF A WRAP WILL BE NEEDED */
+
+		    gp3_cmd_next = gp3_cmd_current + size_dwords;
+		    if ((gp3_cmd_bottom - gp3_cmd_next) <= GP3_MAX_COMMAND_SIZE)
+		    {
+			    gp3_cmd_next  = gp3_cmd_top;
+    			
+			    /* WAIT FOR HARDWARE */
+    			
+			    GP3_WAIT_WRAP(temp);
+			    WRITE_COMMAND32 (0, GP3_DATA_LOAD_HDR_TYPE | GP3_DATA_LOAD_HDR_WRAP |
+				    GP3_DATA_LOAD_HDR_ENABLE);
+		    }
+		    else
+		    {
+			    /* WAIT FOR AVAILABLE SPACE */
+
+			    GP3_WAIT_PRIMITIVE(temp);
+			    WRITE_COMMAND32 (0, GP3_DATA_LOAD_HDR_TYPE | GP3_DATA_LOAD_HDR_ENABLE);
+		    }
+
+		    /* WRITE DWORD COUNT */
+    		
+		    WRITE_COMMAND32 (4, GP3_CH3_HOST_SOURCE_TYPE | total_dwords);
+
+		    /* WRITE DATA */
+
+		    WRITE_COMMAND_STRING32 (8, data, srcoffset, dword_count);
+		    WRITE_COMMAND_STRING8 (8 + (dword_count << 2), data,
+			    srcoffset + (dword_count << 2), byte_count);
+
+		    /* UPDATE POINTERS */
+
+		    srcoffset += pitch;
+		    WRITE_GP32 (GP3_CMD_WRITE, gp3_cmd_next);
+		    gp3_cmd_current = gp3_cmd_next;
+	    }
+    }
+}
+
+/*---------------------------------------------------------------------------
+ * gp_custom_convert_blt
+ *
+ * This routine is identical to gp_color_convert_blt, except that the macro
+ * to write data to the frame buffer has been replaced with a new macro.  This
+ * allows a user to implement custom behavior when sending data, such as manually
+ * converting 24BPP to 32BPP, converting 2BPP to 4BPP or premultiplying alpha data.
+ *-------------------------------------------------------------------------*/
+
+void gp_custom_convert_blt (unsigned long dstoffset, unsigned long srcx,
+    unsigned long width, unsigned long height, unsigned char *data, long pitch)
+{
+	unsigned long indent, temp;
+	unsigned long total_dwords, size_dwords;
+	unsigned long dword_count, byte_count;
+	unsigned long size = ((width << 16) | height);
+	unsigned long ch3_offset, srcoffset;
+    unsigned long ch3_size, base;
+		
+	/* ASSUME BITMAPS ARE DWORD ALIGNED */
+	/* We will offset into the source data in DWORD increments.  We  */
+	/* set the source index to the remaining byte offset and         */
+	/* increment the size of each line to account for the dont-care  */
+	/* pixel(s).   For 4BPP source data, we also set the appropriate */
+	/* nibble index.                                                 */
+	
+    /* CALCULATE THE SIZE OF ONE LINE */
+
+    if ((gp3_src_format & GP3_CH3_SRC_MASK) == GP3_CH3_SRC_24BPP_PACKED)
+    {
+        /* HANDLE 24BPP */
+        /* Note that we do not do anything to guarantee that the source data      */
+        /* is DWORD aligned.  The logic here is that the source data will be      */
+        /* cacheable, in which case Geode LX will not lose any clocks for unaligned */
+        /* moves.  Also note that the channel 3 width is programmed as the        */
+        /* number of dwords, while the normal width is programmed as the number   */
+        /* of pixels.                                                             */
+
+        srcoffset  = srcx * 3;
+        ch3_offset = 0;
+        temp       = width * 3;
+        ch3_size   = (((temp + 3) >> 2) << 16) | height;
+    }
+    else
+    {
+        ch3_size = size;
+
+	    if (gp3_src_pix_shift == 3)
+	    {
+		    /* CALCULATE INDENT AND SOURCE OFFSET */
+
+		    indent     = (srcx >> 1);
+		    srcoffset  = (indent & ~3L);
+		    indent    &= 3;
+		    ch3_offset = indent | ((srcx & 1) << 25);
+
+		    temp = ((width + (srcx & 1) + 1) >> 1) + indent;
+	    }
+	    else
+	    {
+		    indent     = (srcx << gp3_src_pix_shift);
+		    srcoffset  = (indent & ~3L);
+		    indent    &= 3;
+		    ch3_offset = indent;
+
+		    temp = (width << gp3_src_pix_shift) + indent;
+	    }
+    }
+
+	total_dwords = (temp + 3) >> 2;
+	size_dwords  = (total_dwords << 2) + 8;
+	dword_count  = (temp >> 2);
+	byte_count   = (temp & 3);
+
+    base = ((gp3_fb_base << 24) + (dstoffset & 0xFFC00000)) |
+           (gp3_base_register & ~GP3_BASE_OFFSET_DSTMASK);
+
+	/* SET APPROPRIATE ENABLES */
+
+	gp3_cmd_header |= GP3_BLT_HDR_DST_OFF_ENABLE     |
+					  GP3_BLT_HDR_WIDHI_ENABLE       |
+					  GP3_BLT_HDR_CH3_STR_ENABLE     |
+					  GP3_BLT_HDR_CH3_OFF_ENABLE     |
+					  GP3_BLT_HDR_CH3_WIDHI_ENABLE   |
+					  GP3_BLT_HDR_BASE_OFFSET_ENABLE |
+					  GP3_BLT_HDR_BLT_MODE_ENABLE;
+
+	WRITE_COMMAND32 (GP3_BLT_DST_OFFSET, (dstoffset & 0x3FFFFF) | gp3_pat_origin);
+	WRITE_COMMAND32 (GP3_BLT_CH3_OFFSET, ch3_offset);
+	WRITE_COMMAND32 (GP3_BLT_WID_HEIGHT, size);
+	WRITE_COMMAND32 (GP3_BLT_CH3_WIDHI, ch3_size);
+	WRITE_COMMAND32 (GP3_BLT_BASE_OFFSET, base);
+	WRITE_COMMAND32 (GP3_BLT_CH3_MODE_STR,
+		GP3_CH3_C3EN           |
+		GP3_CH3_REPLACE_SOURCE |
+		GP3_CH3_HST_SRC_ENABLE |
+		gp3_src_format         |
+	  ((gp3_blt_flags & CIMGP_BLTFLAGS_PRES_LUT) << 20));
+	WRITE_COMMAND32 (GP3_BLT_MODE, gp3_blt_mode);
+
+	/* START THE BLT */
+
+	WRITE_COMMAND32 (GP3_BLT_CMD_HEADER, gp3_cmd_header);
+	WRITE_GP32 (GP3_CMD_WRITE, gp3_cmd_next);
+	gp3_cmd_current = gp3_cmd_next;
+
+    if (((total_dwords << 2) * height) <= GP3_BLT_1PASS_SIZE &&
+        (gp3_cmd_bottom - gp3_cmd_current) > (GP3_BLT_1PASS_SIZE + 72))
+    {
+        /* UPDATE THE COMMAND POINTER */
+
+		cim_cmd_ptr = cim_cmd_base_ptr + gp3_cmd_current;
+
+        /* CHECK IF A WRAP WILL BE NEEDED */
+
+		gp3_cmd_next = gp3_cmd_current + ((total_dwords << 2) * height) + 8;
+
+	    if ((gp3_cmd_bottom - gp3_cmd_next) <= GP3_MAX_COMMAND_SIZE)
+		{
+			gp3_cmd_next  = gp3_cmd_top;
+            	
+			GP3_WAIT_WRAP(temp);
+			WRITE_COMMAND32 (0, GP3_DATA_LOAD_HDR_TYPE | GP3_DATA_LOAD_HDR_WRAP |
+				GP3_DATA_LOAD_HDR_ENABLE);
+		}
+		else
+		{
+			GP3_WAIT_PRIMITIVE(temp);
+			WRITE_COMMAND32 (0, GP3_DATA_LOAD_HDR_TYPE | GP3_DATA_LOAD_HDR_ENABLE);
+		}
+
+        /* WRITE DWORD COUNT */
+
+		WRITE_COMMAND32 (4, GP3_CH3_HOST_SOURCE_TYPE | (total_dwords * height));
+
+        while (height--)
+	    {
+		    /* WRITE DATA */
+
+		    WRITE_CUSTOM_COMMAND_STRING32 (8, data, srcoffset, dword_count);
+		    WRITE_CUSTOM_COMMAND_STRING8 (8 + (dword_count << 2), data,
+			    srcoffset + (dword_count << 2), byte_count);
+
+		    srcoffset += pitch;
+            cim_cmd_ptr += total_dwords << 2;
+	    }
+
+        WRITE_GP32 (GP3_CMD_WRITE, gp3_cmd_next);
+		gp3_cmd_current = gp3_cmd_next;
+    }
+    else
+    {
+	    /* WRITE DATA LINE BY LINE */
+	    /* Each line will be created as a separate command buffer entry to allow */
+	    /* line-by-line wrapping and to allow simultaneous rendering by the HW.  */
+    	
+	    while (height--)
+	    {
+		    /* UPDATE THE COMMAND POINTER */
+		    /* The WRITE_COMMANDXX macros use a pointer to the current buffer space. */
+		    /* This is created by adding gp3_cmd_current to the base pointer.        */
+
+		    cim_cmd_ptr = cim_cmd_base_ptr + gp3_cmd_current;
+
+		    /* CHECK IF A WRAP WILL BE NEEDED */
+
+		    gp3_cmd_next = gp3_cmd_current + size_dwords;
+		    if ((gp3_cmd_bottom - gp3_cmd_next) <= GP3_MAX_COMMAND_SIZE)
+		    {
+			    gp3_cmd_next  = gp3_cmd_top;
+    			
+			    /* WAIT FOR HARDWARE */
+    			
+			    GP3_WAIT_WRAP(temp);
+			    WRITE_COMMAND32 (0, GP3_DATA_LOAD_HDR_TYPE | GP3_DATA_LOAD_HDR_WRAP |
+				    GP3_DATA_LOAD_HDR_ENABLE);
+		    }
+		    else
+		    {
+			    /* WAIT FOR AVAILABLE SPACE */
+
+			    GP3_WAIT_PRIMITIVE(temp);
+			    WRITE_COMMAND32 (0, GP3_DATA_LOAD_HDR_TYPE | GP3_DATA_LOAD_HDR_ENABLE);
+		    }
+
+		    /* WRITE DWORD COUNT */
+    		
+		    WRITE_COMMAND32 (4, GP3_CH3_HOST_SOURCE_TYPE | total_dwords);
+
+		    /* WRITE DATA */
+
+		    WRITE_CUSTOM_COMMAND_STRING32 (8, data, srcoffset, dword_count);
+		    WRITE_CUSTOM_COMMAND_STRING8 (8 + (dword_count << 2), data,
+			    srcoffset + (dword_count << 2), byte_count);
+
+		    /* UPDATE POINTERS */
+
+		    srcoffset += pitch;
+		    WRITE_GP32 (GP3_CMD_WRITE, gp3_cmd_next);
+		    gp3_cmd_current = gp3_cmd_next;
+	    }
+    }
+}
+
+/*---------------------------------------------------------------------------
+ * gp_rotate_blt
+ *
+ * This routine is called to rotate a rectangular area of video memory.  The
+ * data may be color converted during the rotation.  'Degrees' must be a
+ * multiple of 90 and indicates a clockwise rotation.  Width and height
+ * refer to the width and the height of the source.  The output
+ * destinations will be equal to the rotated dimensions.
+ *-------------------------------------------------------------------------*/
+
+void gp_rotate_blt (unsigned long dstoffset, unsigned long srcoffset,
+	unsigned long width, unsigned long height, int degrees)
+{
+	unsigned long sizein, sizeout;
+	unsigned long ch3_flags;
+    unsigned long base;
+
+    base = ((gp3_fb_base << 24) + (dstoffset & 0xFFC00000))         |
+	       ((gp3_fb_base << 4)  + ((srcoffset & 0xFFC00000) >> 20)) |
+            (gp3_base_register & GP3_BASE_OFFSET_SRCMASK);
+
+    srcoffset &= 0x3FFFFF;
+    dstoffset &= 0x3FFFFF;
+
+	/* SET ROTATION PARAMETERS */
+
+	switch (degrees)
+	{
+		case 90:
+			srcoffset += (height - 1) * gp3_src_stride;
+			sizein     = ((width  << 16) | height);
+			sizeout    = ((height << 16) | width);
+			ch3_flags  = GP3_CH3_C3EN           |
+				         GP3_CH3_REPLACE_SOURCE |
+						 GP3_CH3_ROTATE_ENABLE  |
+						 GP3_CH3_NEG_YDIR;	
+			break;
+
+		case 180:
+			srcoffset += (height - 1) * gp3_src_stride;
+			srcoffset += (width << gp3_src_pix_shift) - 1;
+			sizein     = sizeout = ((width  << 16) | height);
+			ch3_flags  = GP3_CH3_C3EN           |
+				         GP3_CH3_REPLACE_SOURCE |
+						 GP3_CH3_NEG_YDIR       |
+						 GP3_CH3_NEG_XDIR;	
+			break;
+
+		case 270:
+			srcoffset +=  (width << gp3_src_pix_shift) - 1;
+			sizein     = ((width  << 16) | height);
+			sizeout    = ((height << 16) | width);
+			ch3_flags  = GP3_CH3_C3EN           |
+				         GP3_CH3_REPLACE_SOURCE |
+						 GP3_CH3_ROTATE_ENABLE  |
+						 GP3_CH3_NEG_XDIR;	
+			break;
+
+		default:
+			sizein     = sizeout = ((width  << 16) | height);
+			ch3_flags  = GP3_CH3_C3EN |
+				         GP3_CH3_REPLACE_SOURCE;
+			break;		
+	}
+
+	/* SET APPROPRIATE ENABLES                           */
+	/* We override the raster mode setting with a source */
+	/* copy ROP.                                         */
+
+	gp3_cmd_header |= GP3_BLT_HDR_RASTER_ENABLE      |
+		              GP3_BLT_HDR_DST_OFF_ENABLE     |
+		              GP3_BLT_HDR_WIDHI_ENABLE       |
+					  GP3_BLT_HDR_CH3_OFF_ENABLE     |
+					  GP3_BLT_HDR_CH3_STR_ENABLE     |
+					  GP3_BLT_HDR_CH3_WIDHI_ENABLE   |
+					  GP3_BLT_HDR_BASE_OFFSET_ENABLE |
+					  GP3_BLT_HDR_BLT_MODE_ENABLE;
+
+	/* WRITE ALL BLT REGISTERS */
+	
+	WRITE_COMMAND32 (GP3_BLT_RASTER_MODE, gp3_bpp | 0xCC);
+	WRITE_COMMAND32 (GP3_BLT_DST_OFFSET, dstoffset);
+	WRITE_COMMAND32 (GP3_BLT_WID_HEIGHT, sizeout);
+	WRITE_COMMAND32 (GP3_BLT_CH3_WIDHI, sizein);
+	WRITE_COMMAND32 (GP3_BLT_CH3_OFFSET, srcoffset);
+	WRITE_COMMAND32 (GP3_BLT_CH3_MODE_STR,
+		ch3_flags                                       |
+		gp3_src_format                                  |
+	  ((gp3_blt_flags & CIMGP_BLTFLAGS_PRES_LUT) << 20) |
+	  ((gp3_blt_flags & CIMGP_ENABLE_PREFETCH)   << 17) |
+	    gp3_src_stride);
+	WRITE_COMMAND32 (GP3_BLT_BASE_OFFSET, base);
+
+	/* START THE BLT */
+
+	WRITE_COMMAND32 (GP3_BLT_CMD_HEADER, gp3_cmd_header);
+	WRITE_COMMAND32 (GP3_BLT_MODE, gp3_blt_mode);
+	WRITE_GP32 (GP3_CMD_WRITE, gp3_cmd_next);
+	gp3_cmd_current = gp3_cmd_next;
+}
+
+/*---------------------------------------------------------------------------
+ * gp_mono_bitmap_to_screen_blt
+ *
+ * This routine expands and BLTs a monchrome bitmap that is stored in system
+ * memory into the framebuffer.  'data' points to an array of monochrome data.
+ * 'stride' indicates the pitch between successive lines of monochrome data.
+ * 'srcx' indicates the x coordinate within each line of blend data
+ * corresponding to the first pixel.  A y coordinate for the source is
+ * deliberately omitted to avoid extra calculation for simple cases that have
+ * no y index.  The calling program must adjust the data pointer accordingly.
+ *-------------------------------------------------------------------------*/
+
+void gp_mono_bitmap_to_screen_blt (unsigned long dstoffset, unsigned long srcx,
+	unsigned long width, unsigned long height, unsigned char *data, long stride)
+{
+	unsigned long indent, temp;
+	unsigned long total_dwords, size_dwords;
+	unsigned long dword_count, byte_count;
+	unsigned long size = ((width << 16) | height);
+	unsigned long srcoffset, src_value;
+
+    /* ASSUME BITMAPS ARE DWORD ALIGNED */
+	/* We will offset into the source data in DWORD increments.  We */
+	/* set the source index to the remaining byte offset and        */
+	/* increment the size of each line to account for the dont-care */
+	/* pixel(s).                                                    */
+
+	indent    = (srcx >> 3);
+	srcoffset = (indent & ~3L);
+	indent   &= 3;
+	src_value = (indent | ((srcx & 7) << 26));
+
+    /* PROGRAM THE NORMAL SOURCE CHANNEL REGISTERS                */
+	/* We assume that a color pattern is being ROPed with source  */
+	/* data if the pattern type is color and the preserve pattern */
+	/* was set.                                                   */
+
+	gp3_cmd_header |= GP3_BLT_HDR_SRC_OFF_ENABLE     |
+		              GP3_BLT_HDR_DST_OFF_ENABLE     |
+					  GP3_BLT_HDR_WIDHI_ENABLE       |
+					  GP3_BLT_HDR_CH3_STR_ENABLE     |
+					  GP3_BLT_HDR_BASE_OFFSET_ENABLE |
+                      GP3_BLT_HDR_RASTER_ENABLE      |
+					  GP3_BLT_HDR_BLT_MODE_ENABLE;
+
+    if (gp3_ch3_pat)
+	{
+		gp3_cmd_header |= GP3_BLT_HDR_CH3_OFF_ENABLE | GP3_BLT_HDR_CH3_WIDHI_ENABLE;
+
+		WRITE_COMMAND32 (GP3_BLT_CH3_OFFSET, gp3_pat_origin);
+		WRITE_COMMAND32 (GP3_BLT_DST_OFFSET, (dstoffset & 0x3FFFFF));
+		WRITE_COMMAND32 (GP3_BLT_CH3_MODE_STR, gp3_pat_format);
+        WRITE_COMMAND32 (GP3_BLT_CH3_WIDHI, size);
+	}
+	else
+	{
+		WRITE_COMMAND32 (GP3_BLT_DST_OFFSET, ((dstoffset & 0x3FFFFF) | gp3_pat_origin));
+		WRITE_COMMAND32 (GP3_BLT_CH3_MODE_STR, 0);
+	}
+    if (gp3_blt_flags & CIMGP_BLTFLAGS_INVERTMONO)
+    {    
+        WRITE_COMMAND32 (GP3_BLT_RASTER_MODE, gp3_raster_mode | GP3_RM_SOURCE_INVERT);
+    }
+    else
+    {
+        WRITE_COMMAND32 (GP3_BLT_RASTER_MODE, gp3_raster_mode & ~GP3_RM_SOURCE_INVERT);
+    }
+	WRITE_COMMAND32 (GP3_BLT_SRC_OFFSET, src_value);
+	WRITE_COMMAND32 (GP3_BLT_WID_HEIGHT, size);
+	WRITE_COMMAND32 (GP3_BLT_BASE_OFFSET,
+		((gp3_fb_base << 24) + (dstoffset & 0xFFC00000)));
+	WRITE_COMMAND32 (GP3_BLT_MODE, gp3_blt_mode | GP3_BM_SRC_HOST | GP3_BM_SRC_MONO);
+		
+	/* START THE BLT */
+
+	WRITE_COMMAND32 (GP3_BLT_CMD_HEADER, gp3_cmd_header);
+	WRITE_GP32 (GP3_CMD_WRITE, gp3_cmd_next);
+	gp3_cmd_current = gp3_cmd_next;
+
+	/* CALCULATE THE SIZE OF ONE LINE */
+
+	size = ((width + (srcx & 7) + 7) >> 3) + indent;
+	total_dwords = (size + 3) >> 2;
+	size_dwords  = (total_dwords << 2) + 8;
+	dword_count  = (size >> 2);
+	byte_count   = (size & 3);
+
+    /* CHECK FOR SMALL BLT CASE */
+    /* If the total amount of monochrome data is less than 50K and we have */
+    /* room in the command buffer, we will do all data writes in a single  */
+    /* data packet.                                                        */
+
+    if (((total_dwords << 2) * height) <= GP3_BLT_1PASS_SIZE &&
+        (gp3_cmd_bottom - gp3_cmd_current) > (GP3_BLT_1PASS_SIZE + 72))
+    {
+        /* UPDATE THE COMMAND POINTER */
+
+		cim_cmd_ptr = cim_cmd_base_ptr + gp3_cmd_current;
+
+        /* CHECK IF A WRAP WILL BE NEEDED */
+
+		gp3_cmd_next = gp3_cmd_current + ((total_dwords << 2) * height) + 8;
+
+	    if ((gp3_cmd_bottom - gp3_cmd_next) <= GP3_MAX_COMMAND_SIZE)
+		{
+			gp3_cmd_next  = gp3_cmd_top;
+        	        	
+			GP3_WAIT_WRAP(temp);
+			WRITE_COMMAND32 (0, GP3_DATA_LOAD_HDR_TYPE | GP3_DATA_LOAD_HDR_WRAP |
+				GP3_DATA_LOAD_HDR_ENABLE);
+		}
+		else
+		{
+			GP3_WAIT_PRIMITIVE(temp);
+			WRITE_COMMAND32 (0, GP3_DATA_LOAD_HDR_TYPE | GP3_DATA_LOAD_HDR_ENABLE);
+		}
+
+        /* WRITE DWORD COUNT */
+        	
+		WRITE_COMMAND32 (4, GP3_HOST_SOURCE_TYPE | (total_dwords * height));
+
+        while (height--)
+	    {
+		    /* WRITE DATA */
+
+		    WRITE_COMMAND_STRING32 (8, data, srcoffset, dword_count);
+		    WRITE_COMMAND_STRING8 (8 + (dword_count << 2), data,
+			    srcoffset + (dword_count << 2), byte_count);
+
+		    srcoffset += stride;
+            cim_cmd_ptr += total_dwords << 2;
+	    }
+
+        WRITE_GP32 (GP3_CMD_WRITE, gp3_cmd_next);
+		gp3_cmd_current = gp3_cmd_next;
+    }
+    else
+    {
+	    /* WRITE DATA LINE BY LINE */
+	    /* Each line will be created as a separate command buffer entry to allow */
+	    /* line-by-line wrapping and to allow simultaneous rendering by the HW.  */
+    	
+	    while (height--)
+	    {
+		    /* UPDATE THE COMMAND POINTER */
+		    /* The WRITE_COMMANDXX macros use a pointer to the current buffer space. */
+		    /* This is created by adding gp3_cmd_current to the base pointer.        */
+
+		    cim_cmd_ptr = cim_cmd_base_ptr + gp3_cmd_current;
+
+		    /* CHECK IF A WRAP WILL BE NEEDED */
+
+		    gp3_cmd_next = gp3_cmd_current + size_dwords;
+		    if ((gp3_cmd_bottom - gp3_cmd_next) <= GP3_MAX_COMMAND_SIZE)
+		    {
+			    gp3_cmd_next  = gp3_cmd_top;
+    			
+			    /* WAIT FOR HARDWARE */
+    			
+			    GP3_WAIT_WRAP(temp);
+			    WRITE_COMMAND32 (0, GP3_DATA_LOAD_HDR_TYPE | GP3_DATA_LOAD_HDR_WRAP |
+				    GP3_DATA_LOAD_HDR_ENABLE);
+		    }
+		    else
+		    {
+			    /* WAIT FOR AVAILABLE SPACE */
+
+			    GP3_WAIT_PRIMITIVE(temp);
+			    WRITE_COMMAND32 (0, GP3_DATA_LOAD_HDR_TYPE | GP3_DATA_LOAD_HDR_ENABLE);
+		    }
+
+		    /* WRITE DWORD COUNT */
+    		
+		    WRITE_COMMAND32 (4, GP3_HOST_SOURCE_TYPE | total_dwords);
+
+		    /* WRITE DATA */
+
+		    WRITE_COMMAND_STRING32 (8, data, srcoffset, dword_count);
+		    WRITE_COMMAND_STRING8 (8 + (dword_count << 2), data,
+			    srcoffset + (dword_count << 2), byte_count);
+
+		    /* UPDATE POINTERS */
+
+		    srcoffset += stride;
+		    WRITE_GP32 (GP3_CMD_WRITE, gp3_cmd_next);
+		    gp3_cmd_current = gp3_cmd_next;
+        }
+    }
+}
+
+/*---------------------------------------------------------------------------
+ * gp_text_blt
+ *
+ * This routine expands and BLTs byte-packed monochrome data to the screen.
+ * There is assumed to be no x clipping involved in the BLT.
+ *-------------------------------------------------------------------------*/
+
+void gp_text_blt (unsigned long dstoffset, unsigned long width,
+	unsigned long height, unsigned char *data)
+{
+	unsigned long temp, dwords_total;
+	unsigned long dword_count, byte_count;
+	unsigned long size = ((width << 16) | height);
+    unsigned long srcoffset = 0;
+
+	/* PROGRAM THE NORMAL SOURCE CHANNEL REGISTERS                */
+	/* We assume that a color pattern is being ROPed with source  */
+	/* data if the pattern type is color and the preserve pattern */
+	/* was set.                                                   */
+
+	gp3_cmd_header |= GP3_BLT_HDR_SRC_OFF_ENABLE     |
+		              GP3_BLT_HDR_DST_OFF_ENABLE     |
+					  GP3_BLT_HDR_WIDHI_ENABLE       |
+					  GP3_BLT_HDR_CH3_STR_ENABLE     |
+					  GP3_BLT_HDR_BASE_OFFSET_ENABLE |
+                      GP3_BLT_HDR_RASTER_ENABLE      |
+					  GP3_BLT_HDR_BLT_MODE_ENABLE;
+
+    if (gp3_ch3_pat)
+	{
+		gp3_cmd_header |= GP3_BLT_HDR_CH3_OFF_ENABLE | GP3_BLT_HDR_CH3_WIDHI_ENABLE;
+
+		WRITE_COMMAND32 (GP3_BLT_CH3_OFFSET, gp3_pat_origin);
+		WRITE_COMMAND32 (GP3_BLT_DST_OFFSET, (dstoffset & 0x3FFFFF));
+		WRITE_COMMAND32 (GP3_BLT_CH3_MODE_STR, gp3_pat_format);
+        WRITE_COMMAND32 (GP3_BLT_CH3_WIDHI, size);
+	}
+	else
+	{
+		WRITE_COMMAND32 (GP3_BLT_DST_OFFSET, ((dstoffset & 0x3FFFFF) | gp3_pat_origin));
+		WRITE_COMMAND32 (GP3_BLT_CH3_MODE_STR, 0);
+	}
+    if (gp3_blt_flags & CIMGP_BLTFLAGS_INVERTMONO)
+    {    
+        WRITE_COMMAND32 (GP3_BLT_RASTER_MODE, gp3_raster_mode | GP3_RM_SOURCE_INVERT);
+    }
+    else
+    {
+        WRITE_COMMAND32 (GP3_BLT_RASTER_MODE, gp3_raster_mode & ~GP3_RM_SOURCE_INVERT);
+    }
+	
+	WRITE_COMMAND32 (GP3_BLT_SRC_OFFSET, 0);
+	WRITE_COMMAND32 (GP3_BLT_WID_HEIGHT, size);
+	WRITE_COMMAND32 (GP3_BLT_BASE_OFFSET,
+		((gp3_fb_base << 24) + (dstoffset & 0xFFC00000)));
+	WRITE_COMMAND32 (GP3_BLT_MODE, gp3_blt_mode | GP3_BM_SRC_HOST | GP3_BM_SRC_BP_MONO);
+		
+	/* START THE BLT */
+
+	WRITE_COMMAND32 (GP3_BLT_CMD_HEADER, gp3_cmd_header);
+	WRITE_GP32 (GP3_CMD_WRITE, gp3_cmd_next);
+	gp3_cmd_current = gp3_cmd_next;
+
+	/* CALCULATE THE TOTAL NUMBER OF BYTES */
+
+	size = ((width + 7) >> 3) * height;
+
+	/* WRITE ALL DATA IN CHUNKS */
+
+	do
+	{
+		/* UPDATE THE COMMAND POINTER */
+	
+		cim_cmd_ptr = cim_cmd_base_ptr + gp3_cmd_current;
+
+		if (size > 8192)
+		{
+			dword_count = 2048;
+			byte_count  = 0;
+			dwords_total = 2048;
+			size -= 8192;
+		}
+		else
+		{
+			dword_count = (size >> 2);
+			byte_count  = (size & 3);
+			dwords_total = (size + 3) >> 2;
+			size = 0;
+		}
+		gp3_cmd_next = gp3_cmd_current + (dwords_total << 2) + 8;
+
+		/* CHECK IF A WRAP WILL BE NEEDED */
+
+		if ((gp3_cmd_bottom - gp3_cmd_next) <= GP3_MAX_COMMAND_SIZE)
+		{
+			gp3_cmd_next  = gp3_cmd_top;
+				
+			/* WAIT FOR HARDWARE */
+				
+			GP3_WAIT_WRAP(temp);
+			WRITE_COMMAND32 (0, GP3_DATA_LOAD_HDR_TYPE | GP3_DATA_LOAD_HDR_WRAP |
+				GP3_DATA_LOAD_HDR_ENABLE);
+		}
+		else
+		{
+			/* WAIT FOR AVAILABLE SPACE */
+
+			GP3_WAIT_PRIMITIVE(temp);
+			WRITE_COMMAND32 (0, GP3_DATA_LOAD_HDR_TYPE | GP3_DATA_LOAD_HDR_ENABLE);
+		}
+
+		/* WRITE DWORD COUNT */
+		
+		WRITE_COMMAND32 (4, GP3_HOST_SOURCE_TYPE | dwords_total);
+
+		/* WRITE DATA */
+
+		WRITE_COMMAND_STRING32 (8, data, srcoffset, dword_count);
+		WRITE_COMMAND_STRING8 (8 + (dword_count << 2), data,
+			srcoffset + (dword_count << 2), byte_count);
+
+		WRITE_GP32 (GP3_CMD_WRITE, gp3_cmd_next);
+		gp3_cmd_current = gp3_cmd_next;
+	
+        /* UPDATE THE SOURCE OFFSET */
+        /* We add a constant value because the code will loop only if the */
+        /* data exceeds 8192 bytes.                                       */
+
+        srcoffset += 8192;
+
+    } while (size);
+}
+
+/*---------------------------------------------------------------------------
+ * gp_mono_expand_blt
+ *
+ * This routine expands monochrome data that is stored in video memory into
+ * the current BPP.  The source and destination regions are assumed not to
+ * overlap.  The pitch of the source data is specified in gp_set_strides.
+ * 'srcy' is deliberately omitted to prevent extra calculations for simple
+ * applications that have no source indexes.
+ *-------------------------------------------------------------------------*/
+
+void gp_mono_expand_blt (unsigned long dstoffset, unsigned long srcoffset,
+    unsigned long srcx, unsigned long width, unsigned long height, int byte_packed)
+{
+	unsigned long base;
+	unsigned long blt_mode;
+	unsigned long size = ((width << 16) | height);
+
+	/* ADJUST SOURCE OFFSET */
+
+	srcoffset += (srcx >> 3);
+    srcx &= 7;
+
+	/* CALCULATE BASE OFFSET REGISTER */
+
+	base = ((gp3_fb_base << 24) +  (dstoffset & 0xFFC00000))        |
+	       ((gp3_fb_base << 14) + ((srcoffset & 0xFFC00000) >> 10)) |
+            (gp3_base_register & GP3_BASE_OFFSET_CH3MASK);
+
+	/* SET THE SOURCE TYPE */
+
+	if (byte_packed)
+        blt_mode = gp3_blt_mode | GP3_BM_SRC_FB | GP3_BM_SRC_BP_MONO;
+	else
+		blt_mode = gp3_blt_mode | GP3_BM_SRC_FB | GP3_BM_SRC_MONO;
+
+	/* SET HEADER ENABLES */
+
+	gp3_cmd_header |= GP3_BLT_HDR_SRC_OFF_ENABLE     |
+			          GP3_BLT_HDR_DST_OFF_ENABLE     |
+					  GP3_BLT_HDR_WIDHI_ENABLE       |
+					  GP3_BLT_HDR_CH3_STR_ENABLE     |
+					  GP3_BLT_HDR_BASE_OFFSET_ENABLE |
+                      GP3_BLT_HDR_RASTER_ENABLE      |
+					  GP3_BLT_HDR_BLT_MODE_ENABLE;
+
+	/* ENABLE COLOR PATTERN IF APPLICABLE */
+
+    if (gp3_ch3_pat)
+	{
+		gp3_cmd_header |= GP3_BLT_HDR_CH3_OFF_ENABLE | GP3_BLT_HDR_CH3_WIDHI_ENABLE;
+
+		WRITE_COMMAND32 (GP3_BLT_CH3_OFFSET, gp3_pat_origin);
+		WRITE_COMMAND32 (GP3_BLT_DST_OFFSET, (dstoffset & 0x3FFFFF));
+		WRITE_COMMAND32 (GP3_BLT_CH3_MODE_STR, gp3_pat_format);
+        WRITE_COMMAND32 (GP3_BLT_CH3_WIDHI, size);
+	}
+	else
+	{
+		WRITE_COMMAND32 (GP3_BLT_DST_OFFSET, ((dstoffset & 0x3FFFFF) | gp3_pat_origin));
+		WRITE_COMMAND32 (GP3_BLT_CH3_MODE_STR, 0);
+	}
+    if (gp3_blt_flags & CIMGP_BLTFLAGS_INVERTMONO)
+    {    
+        WRITE_COMMAND32 (GP3_BLT_RASTER_MODE, gp3_raster_mode | GP3_RM_SOURCE_INVERT);
+    }
+    else
+    {
+        WRITE_COMMAND32 (GP3_BLT_RASTER_MODE, gp3_raster_mode & ~GP3_RM_SOURCE_INVERT);
+    }
+
+    WRITE_COMMAND32 (GP3_BLT_BASE_OFFSET, base);	
+	WRITE_COMMAND32 (GP3_BLT_SRC_OFFSET,
+		(srcoffset & 0x3FFFFF) | (srcx << 26));
+	WRITE_COMMAND32 (GP3_BLT_WID_HEIGHT, size);
+			
+    /* WORKAROUND FOR SIBZ #3744 */
+    /* Under extremely rare conditions, very narrow byte-packed mono BLTs can hang  */
+    /* the GP.  Even under the rare case, the bad condition will only happen        */
+    /* once every 16 lines.  The workaround is to break the offending BLT into a    */
+    /* a series of safer BLTs.  This method is preferred over a two-pass approach   */
+    /* because it does not require saving and restoring any GP state, such as the   */
+    /* ROP or mono colors.                                                          */
+
+    if ((gp3_blt_mode & GP3_BM_DST_REQ) && byte_packed && (gp3_pix_shift < 2) &&
+        (width < 5) && ((srcoffset & 0x1F) == 0x1F) && ((srcx + width) > 8))
+    {
+        unsigned long dstoff1, size1, org1;
+        unsigned long dstoff2, size2, org2;
+        unsigned long tempheight;
+
+        size1 = ((8 - srcx) << 16) | 1;
+        size2 = ((width + srcx - 8) << 16) | 1;
+        org1  = gp3_pat_origin;
+        org2  = (org1 & 0xE0000000) | ((org1 + ((8 - srcx) << 26)) & 0x1C000000);
+        dstoff1 = dstoffset & 0x3FFFFF;
+        dstoff2 = (dstoff1 + 8 - srcx) << gp3_pix_shift;
+
+        while (height)
+        {
+            /* DIVIDE THE FIRST LINE INTO TWO SINGLE LINE BLTS */
+
+            WRITE_COMMAND32 (GP3_BLT_WID_HEIGHT, size1);
+            WRITE_COMMAND32 (GP3_BLT_CH3_WIDHI,  size1);
+            WRITE_COMMAND32 (GP3_BLT_SRC_OFFSET, (srcoffset & 0x3FFFFF) | (srcx << 26));
+            WRITE_COMMAND32 (GP3_BLT_DST_OFFSET, dstoff1 | org1);
+            WRITE_COMMAND32 (GP3_BLT_CH3_OFFSET, org1);
+            WRITE_COMMAND32 (GP3_BLT_CMD_HEADER, gp3_cmd_header);
+	        WRITE_COMMAND32 (GP3_BLT_MODE, blt_mode);
+	        WRITE_GP32 (GP3_CMD_WRITE, gp3_cmd_next);
+	        gp3_cmd_current = gp3_cmd_next;
+            gp_wait_until_idle();
+
+            gp_declare_blt (gp3_blt_flags);
+            gp3_cmd_header |= GP3_BLT_HDR_SRC_OFF_ENABLE     |
+			                  GP3_BLT_HDR_DST_OFF_ENABLE     |
+					          GP3_BLT_HDR_WIDHI_ENABLE       |
+					          GP3_BLT_HDR_BLT_MODE_ENABLE    |
+                              GP3_BLT_HDR_CH3_OFF_ENABLE     |
+                              GP3_BLT_HDR_CH3_WIDHI_ENABLE;
+            WRITE_COMMAND32 (GP3_BLT_WID_HEIGHT, size2);
+            WRITE_COMMAND32 (GP3_BLT_CH3_WIDHI,  size2);
+            WRITE_COMMAND32 (GP3_BLT_SRC_OFFSET, ((srcoffset + 1) & 0x3FFFFF));
+            WRITE_COMMAND32 (GP3_BLT_DST_OFFSET, dstoff2 | org2);
+            WRITE_COMMAND32 (GP3_BLT_CH3_OFFSET, org2);
+            WRITE_COMMAND32 (GP3_BLT_CMD_HEADER, gp3_cmd_header);
+	        WRITE_COMMAND32 (GP3_BLT_MODE, blt_mode);
+	        WRITE_GP32 (GP3_CMD_WRITE, gp3_cmd_next);
+	        gp3_cmd_current = gp3_cmd_next;
+            gp_wait_until_idle();
+
+            if (--height)
+            {
+                org1 += 0x20000000;
+                org2 += 0x20000000;
+                dstoff1 += gp3_dst_stride;
+                dstoff2 += gp3_dst_stride;
+                srcoffset += 2;
+
+                /* THE NEXT 15 LINES ARE NOW 'SAFE' - THEY DO NOT SHOW THE PROBLEM */
+
+                tempheight = 15;
+                if (tempheight > height)
+                    tempheight = height;
+
+                gp_declare_blt (gp3_blt_flags);
+                gp3_cmd_header |= GP3_BLT_HDR_SRC_OFF_ENABLE     |
+			                    GP3_BLT_HDR_DST_OFF_ENABLE     |
+					            GP3_BLT_HDR_WIDHI_ENABLE       |
+					            GP3_BLT_HDR_BLT_MODE_ENABLE    |
+                                GP3_BLT_HDR_CH3_OFF_ENABLE     |
+                                GP3_BLT_HDR_CH3_WIDHI_ENABLE;
+                WRITE_COMMAND32 (GP3_BLT_WID_HEIGHT, (width << 16) | tempheight);
+                WRITE_COMMAND32 (GP3_BLT_CH3_WIDHI,  (width << 16) | tempheight);
+                WRITE_COMMAND32 (GP3_BLT_SRC_OFFSET, (srcoffset & 0x3FFFFF) | (srcx << 26));
+                WRITE_COMMAND32 (GP3_BLT_DST_OFFSET, dstoff1 | org1);
+                WRITE_COMMAND32 (GP3_BLT_CH3_OFFSET, org1);
+                WRITE_COMMAND32 (GP3_BLT_CMD_HEADER, gp3_cmd_header);
+	            WRITE_COMMAND32 (GP3_BLT_MODE, blt_mode);
+	            WRITE_GP32 (GP3_CMD_WRITE, gp3_cmd_next);
+	            gp3_cmd_current = gp3_cmd_next;
+                gp_wait_until_idle();
+
+                height -= tempheight;
+
+                if (height)
+                {
+                    gp_declare_blt (gp3_blt_flags);
+                    gp3_cmd_header |= GP3_BLT_HDR_SRC_OFF_ENABLE     |
+			                        GP3_BLT_HDR_DST_OFF_ENABLE     |
+					                GP3_BLT_HDR_WIDHI_ENABLE       |
+					                GP3_BLT_HDR_BLT_MODE_ENABLE    |
+                                    GP3_BLT_HDR_CH3_OFF_ENABLE     |
+                                    GP3_BLT_HDR_CH3_WIDHI_ENABLE;
+
+                    /* ADJUST ORIGIN */
+                    /* If we get here, we added a full 15 lines which is equivalent */
+                    /* to subtracting one from the pattern y origin (adding 15).    */
+
+                    org1 -= 0x20000000;
+                    org2 -= 0x20000000;
+                    dstoff1 += (gp3_dst_stride * 15);
+                    dstoff2 += (gp3_dst_stride * 15);
+                    srcoffset += 30;
+                }
+            }
+        }
+        return;
+    }
+
+	/* START THE BLT */
+
+	WRITE_COMMAND32 (GP3_BLT_CMD_HEADER, gp3_cmd_header);
+	WRITE_COMMAND32 (GP3_BLT_MODE, blt_mode);
+	WRITE_GP32 (GP3_CMD_WRITE, gp3_cmd_next);
+	gp3_cmd_current = gp3_cmd_next;
+}
+
+/*---------------------------------------------------------------------------
+ * gp_antialiased_text
+ *
+ * This routine implements alpha blending between a constant source color and
+ * a destination region.  The degree of the blend is controlled by an array
+ * of 4BPP/8BPP values specified in 'data'.  'stride' indicates the pitch between
+ * successive lines of blend data.  'srcx' indicates the x coordinate within
+ * each line of blend data corresponding to the first pixel.  A y coordinate
+ * for the source is deliberately omitted to avoid extra calculation for simple
+ * cases that have no y index.  The calling program must adjust the data
+ * pointer accordingly.  'fourbpp' selects between 4BPP and 8BPP alpha.
+ *-------------------------------------------------------------------------*/
+
+void gp_antialiased_text (unsigned long dstoffset, unsigned long srcx,
+	unsigned long width, unsigned long height, unsigned char *data, long stride,
+	int fourbpp)
+{
+	unsigned long indent, temp;
+	unsigned long total_dwords, size_dwords;
+	unsigned long dword_count, byte_count;
+	unsigned long size = ((width << 16) | height);
+	unsigned long ch3_offset, srcoffset;
+    unsigned long base, depth_flag;
+
+    base = ((gp3_fb_base << 24) + (dstoffset & 0xFFC00000)) |
+            (gp3_base_register & ~GP3_BASE_OFFSET_DSTMASK);
+
+	/* ENABLE ALL RELEVANT REGISTERS */
+	/* We override the raster mode register to force the */
+	/* correct alpha blend                               */
+
+	gp3_cmd_header |= GP3_BLT_HDR_RASTER_ENABLE      |
+		              GP3_BLT_HDR_DST_OFF_ENABLE     |
+					  GP3_BLT_HDR_WIDHI_ENABLE       |
+					  GP3_BLT_HDR_CH3_OFF_ENABLE     |
+					  GP3_BLT_HDR_CH3_STR_ENABLE     |
+					  GP3_BLT_HDR_CH3_WIDHI_ENABLE   |
+					  GP3_BLT_HDR_BASE_OFFSET_ENABLE |
+					  GP3_BLT_HDR_BLT_MODE_ENABLE;
+
+	/* CALCULATIONS BASED ON ALPHA DEPTH */
+	/* Although most antialiased text is 4BPP, the hardware supports */
+	/* a full 8BPP.  Either case is supported by this routine.       */
+
+	if (fourbpp)
+	{
+        depth_flag = GP3_CH3_SRC_4BPP_ALPHA;
+		indent     = (srcx >> 1);
+		srcoffset  = (indent & ~3L);
+		indent    &= 3;
+		ch3_offset = indent | ((srcx & 1) << 25);
+
+		temp = ((width + (srcx & 1) + 1) >> 1) + indent;
+	}
+	else
+	{
+        depth_flag  = GP3_CH3_SRC_8BPP_ALPHA;
+		indent     =  srcx;
+		srcoffset  = (indent & ~3L);
+		indent    &= 3;
+		ch3_offset = indent;
+
+		temp = width + indent;
+	}
+
+	total_dwords = (temp + 3) >> 2;
+	size_dwords  = (total_dwords << 2) + 8;
+	dword_count  = (temp >> 2);
+	byte_count   = (temp & 3);
+
+	/* SET RASTER MODE REGISTER */
+	/* Alpha blending will only apply to RGB when no alpha component is present. */
+	/* As 8BPP is not supported for this routine, the only alpha-less mode is    */
+	/* 5:6:5.                                                                    */
+
+	if (gp3_bpp == GP3_RM_BPPFMT_565)
+	{
+		WRITE_COMMAND32 (GP3_BLT_RASTER_MODE,
+			gp3_bpp                    |
+			GP3_RM_ALPHA_TO_RGB        |
+			GP3_RM_ALPHA_A_PLUS_BETA_B |
+			GP3_RM_SELECT_ALPHA_CHAN_3);
+	}
+	else
+	{
+		WRITE_COMMAND32 (GP3_BLT_RASTER_MODE,
+			gp3_bpp                    |
+			GP3_RM_ALPHA_ALL           |
+			GP3_RM_ALPHA_A_PLUS_BETA_B |
+			GP3_RM_SELECT_ALPHA_CHAN_3);
+	}
+
+	/* WRITE ALL REMAINING REGISTERS */
+
+	WRITE_COMMAND32 (GP3_BLT_DST_OFFSET, (dstoffset & 0x3FFFFF));
+	WRITE_COMMAND32 (GP3_BLT_CH3_OFFSET, ch3_offset);
+	WRITE_COMMAND32 (GP3_BLT_WID_HEIGHT, size);
+	WRITE_COMMAND32 (GP3_BLT_CH3_WIDHI, size);
+	WRITE_COMMAND32 (GP3_BLT_BASE_OFFSET, base);
+	WRITE_COMMAND32 (GP3_BLT_CH3_MODE_STR,
+		GP3_CH3_C3EN           |
+		GP3_CH3_HST_SRC_ENABLE |
+		depth_flag             |
+	  ((gp3_blt_flags & CIMGP_BLTFLAGS_PRES_LUT) << 20));
+	WRITE_COMMAND32 (GP3_BLT_MODE, gp3_blt_mode | GP3_BM_DST_REQ);
+
+	/* START THE BLT */
+
+	WRITE_COMMAND32 (GP3_BLT_CMD_HEADER, gp3_cmd_header);
+	WRITE_GP32 (GP3_CMD_WRITE, gp3_cmd_next);
+	gp3_cmd_current = gp3_cmd_next;
+
+	/* WRITE DATA LINE BY LINE */
+	/* Each line will be created as a separate command buffer entry to allow */
+	/* line-by-line wrapping and to allow simultaneous rendering by the HW.  */
+	
+    if (((total_dwords << 2) * height) <= GP3_BLT_1PASS_SIZE &&
+        (gp3_cmd_bottom - gp3_cmd_current) > (GP3_BLT_1PASS_SIZE + 72))
+    {
+        /* UPDATE THE COMMAND POINTER */
+
+		cim_cmd_ptr = cim_cmd_base_ptr + gp3_cmd_current;
+
+        /* CHECK IF A WRAP WILL BE NEEDED */
+
+		gp3_cmd_next = gp3_cmd_current + ((total_dwords << 2) * height) + 8;
+
+	    if ((gp3_cmd_bottom - gp3_cmd_next) <= GP3_MAX_COMMAND_SIZE)
+		{
+			gp3_cmd_next  = gp3_cmd_top;
+        	        	
+			GP3_WAIT_WRAP(temp);
+			WRITE_COMMAND32 (0, GP3_DATA_LOAD_HDR_TYPE | GP3_DATA_LOAD_HDR_WRAP |
+				GP3_DATA_LOAD_HDR_ENABLE);
+		}
+		else
+		{
+			GP3_WAIT_PRIMITIVE(temp);
+			WRITE_COMMAND32 (0, GP3_DATA_LOAD_HDR_TYPE | GP3_DATA_LOAD_HDR_ENABLE);
+		}
+
+        /* WRITE DWORD COUNT */
+        	
+		WRITE_COMMAND32 (4, GP3_CH3_HOST_SOURCE_TYPE | (total_dwords * height));
+
+        while (height--)
+	    {
+		    /* WRITE DATA */
+
+		    WRITE_COMMAND_STRING32 (8, data, srcoffset, dword_count);
+		    WRITE_COMMAND_STRING8 (8 + (dword_count << 2), data,
+			    srcoffset + (dword_count << 2), byte_count);
+
+		    srcoffset += stride;
+            cim_cmd_ptr += total_dwords << 2;
+	    }
+
+        WRITE_GP32 (GP3_CMD_WRITE, gp3_cmd_next);
+		gp3_cmd_current = gp3_cmd_next;
+    }
+    else
+    {
+	    while (height--)
+	    {
+		    /* UPDATE THE COMMAND POINTER */
+		    /* The WRITE_COMMANDXX macros use a pointer to the current buffer space. */
+		    /* This is created by adding gp3_cmd_current to the base pointer.        */
+
+		    cim_cmd_ptr = cim_cmd_base_ptr + gp3_cmd_current;
+
+		    /* CHECK IF A WRAP WILL BE NEEDED */
+
+		    gp3_cmd_next = gp3_cmd_current + size_dwords;
+		    if ((gp3_cmd_bottom - gp3_cmd_next) <= GP3_MAX_COMMAND_SIZE)
+		    {
+			    gp3_cmd_next  = gp3_cmd_top;
+			
+			    /* WAIT FOR HARDWARE */
+			
+			    GP3_WAIT_WRAP(temp);
+			    WRITE_COMMAND32 (0, GP3_DATA_LOAD_HDR_TYPE | GP3_DATA_LOAD_HDR_WRAP |
+				    GP3_DATA_LOAD_HDR_ENABLE);
+		    }
+		    else
+		    {
+			    /* WAIT FOR AVAILABLE SPACE */
+
+			    GP3_WAIT_PRIMITIVE(temp);
+			    WRITE_COMMAND32 (0, GP3_DATA_LOAD_HDR_TYPE | GP3_DATA_LOAD_HDR_ENABLE);
+		    }
+
+		    /* WRITE DWORD COUNT */
+		
+		    WRITE_COMMAND32 (4, GP3_CH3_HOST_SOURCE_TYPE | total_dwords);
+
+		    /* WRITE DATA */
+
+		    WRITE_COMMAND_STRING32 (8, data, srcoffset, dword_count);
+		    WRITE_COMMAND_STRING8 (8 + (dword_count << 2), data,
+			    srcoffset + (dword_count << 2), byte_count);
+
+		    /* UPDATE POINTERS */
+
+		    srcoffset += stride;
+		    WRITE_GP32 (GP3_CMD_WRITE, gp3_cmd_next);
+		    gp3_cmd_current = gp3_cmd_next;
+	    }
+    }
+}
+
+/*---------------------------------------------------------------------------
+ * gp_masked_blt
+ *
+ * This routine copies source data to the screen.  A monochrome mask is used
+ * to specify source transparency.
+ *-------------------------------------------------------------------------*/
+
+void gp_masked_blt (unsigned long dstoffset, unsigned long width,
+	unsigned long height, unsigned long mono_srcx, unsigned long color_srcx,
+	unsigned char *mono_mask, unsigned char *color_data, long mono_pitch,
+	long color_pitch)
+{
+    unsigned long indent, temp;
+	unsigned long total_dwords, size_dwords;
+	unsigned long dword_count, byte_count;
+	unsigned long srcoffset, size;
+    unsigned long i, ch3_offset, base;
+    unsigned long flags = 0;
+
+    if (gp3_blt_flags & CIMGP_BLTFLAGS_INVERTMONO)
+        flags = GP3_RM_SOURCE_INVERT;
+
+    /* MONO CALCULATIONS */
+
+    indent    = (mono_srcx >> 3);
+	srcoffset = (indent & ~3L);
+	indent   &= 3;
+
+    size = ((width + (mono_srcx & 7) + 7) >> 3) + indent;
+	total_dwords = (size + 3) >> 2;
+	size_dwords  = (total_dwords << 2) + 8;
+	dword_count  = (size >> 2);
+	byte_count   = (size & 3);
+	
+    base = ((gp3_fb_base << 24) + (gp3_scratch_base & 0xFFC00000)) |
+            (gp3_base_register & ~GP3_BASE_OFFSET_DSTMASK);
+
+    gp3_cmd_header |= GP3_BLT_HDR_RASTER_ENABLE      |
+                      GP3_BLT_HDR_STRIDE_ENABLE      |
+                      GP3_BLT_HDR_DST_OFF_ENABLE     |
+                      GP3_BLT_HDR_WIDHI_ENABLE       |
+                      GP3_BLT_HDR_CH3_STR_ENABLE     |
+                      GP3_BLT_HDR_CH3_OFF_ENABLE     |
+                      GP3_BLT_HDR_CH3_WIDHI_ENABLE   |
+                      GP3_BLT_HDR_BASE_OFFSET_ENABLE |
+                      GP3_BLT_HDR_BLT_MODE_ENABLE;
+
+    WRITE_COMMAND32 (GP3_BLT_RASTER_MODE, GP3_RM_BPPFMT_8888 | 0xCC);
+    WRITE_COMMAND32 (GP3_BLT_STRIDE, (total_dwords << 2));
+    WRITE_COMMAND32 (GP3_BLT_DST_OFFSET, gp3_scratch_base & 0x3FFFFF);
+    WRITE_COMMAND32 (GP3_BLT_WID_HEIGHT, (total_dwords << 16) | height);
+    WRITE_COMMAND32 (GP3_BLT_CH3_WIDHI, (total_dwords << 16) | height);
+    WRITE_COMMAND32 (GP3_BLT_CH3_OFFSET, 0);
+    WRITE_COMMAND32 (GP3_BLT_BASE_OFFSET, base);
+    WRITE_COMMAND32 (GP3_BLT_CH3_MODE_STR,
+        GP3_CH3_C3EN           |
+		GP3_CH3_REPLACE_SOURCE |
+		GP3_CH3_HST_SRC_ENABLE |
+        GP3_CH3_SRC_8_8_8_8    |
+      ((gp3_blt_flags & CIMGP_BLTFLAGS_PRES_LUT) << 20));
+    WRITE_COMMAND32 (GP3_BLT_MODE, 0);
+    WRITE_COMMAND32 (GP3_BLT_CMD_HEADER, gp3_cmd_header);
+
+    /* START THE BLT */
+
+	WRITE_GP32 (GP3_CMD_WRITE, gp3_cmd_next);
+	gp3_cmd_current = gp3_cmd_next;
+
+    for (i = 0; i < height; i++)
+	{
+		/* UPDATE THE COMMAND POINTER */
+		/* The WRITE_COMMANDXX macros use a pointer to the current buffer space. */
+		/* This is created by adding gp3_cmd_current to the base pointer.        */
+
+		cim_cmd_ptr = cim_cmd_base_ptr + gp3_cmd_current;
+
+		/* CHECK IF A WRAP WILL BE NEEDED */
+
+		gp3_cmd_next = gp3_cmd_current + size_dwords;
+		if ((gp3_cmd_bottom - gp3_cmd_next) <= GP3_MAX_COMMAND_SIZE)
+		{
+			gp3_cmd_next  = gp3_cmd_top;
+    		
+			/* WAIT FOR HARDWARE */
+    		
+			GP3_WAIT_WRAP(temp);
+			WRITE_COMMAND32 (0, GP3_DATA_LOAD_HDR_TYPE | GP3_DATA_LOAD_HDR_WRAP |
+				GP3_DATA_LOAD_HDR_ENABLE);
+		}
+		else
+		{
+			/* WAIT FOR AVAILABLE SPACE */
+
+			GP3_WAIT_PRIMITIVE(temp);
+			WRITE_COMMAND32 (0, GP3_DATA_LOAD_HDR_TYPE | GP3_DATA_LOAD_HDR_ENABLE);
+		}
+
+		/* WRITE DWORD COUNT */
+    	
+		WRITE_COMMAND32 (4, GP3_CH3_HOST_SOURCE_TYPE | total_dwords);
+
+		/* WRITE DATA */
+
+		WRITE_COMMAND_STRING32 (8, mono_mask, srcoffset, dword_count);
+		WRITE_COMMAND_STRING8 (8 + (dword_count << 2), mono_mask,
+			srcoffset + (dword_count << 2), byte_count);
+
+		/* UPDATE POINTERS */
+
+		srcoffset += mono_pitch;
+		WRITE_GP32 (GP3_CMD_WRITE, gp3_cmd_next);
+		gp3_cmd_current = gp3_cmd_next;
+	}
+
+    /* SECOND BLT */
+
+    gp_declare_blt (gp3_blt_flags | CIMGP_BLTFLAGS_HAZARD);
+
+    base = ((gp3_fb_base << 24) +  (dstoffset & 0xFFC00000))                          |
+	       ((gp3_fb_base << 14) + (((gp3_scratch_base + indent) & 0xFFC00000) >> 10)) |
+            (gp3_base_register & GP3_BASE_OFFSET_CH3MASK);
+
+    gp3_cmd_header |= GP3_BLT_HDR_RASTER_ENABLE      |
+                      GP3_BLT_HDR_STRIDE_ENABLE      |
+		              GP3_BLT_HDR_DST_OFF_ENABLE     |
+					  GP3_BLT_HDR_SRC_OFF_ENABLE     |
+		              GP3_BLT_HDR_WIDHI_ENABLE       |
+					  GP3_BLT_HDR_CH3_STR_ENABLE     |
+					  GP3_BLT_HDR_CH3_WIDHI_ENABLE   |
+					  GP3_BLT_HDR_BASE_OFFSET_ENABLE |
+					  GP3_BLT_HDR_CH3_OFF_ENABLE     |
+					  GP3_BLT_HDR_BLT_MODE_ENABLE;
+
+    /* ENABLE TRANSPARENCY AND PATTERN COPY ROP */
+    /* The monochrome data is used as a mask but is otherwise not involved in */
+    /* the BLT.  The color data is routed through the pattern channel.        */
+
+    WRITE_COMMAND32 (GP3_BLT_RASTER_MODE, gp3_bpp | 0xF0 | GP3_RM_SRC_TRANS | flags);
+    WRITE_COMMAND32 (GP3_BLT_STRIDE, (total_dwords << 18) | gp3_dst_stride);
+    WRITE_COMMAND32 (GP3_BLT_DST_OFFSET, dstoffset & 0x3FFFFF);
+    WRITE_COMMAND32 (GP3_BLT_SRC_OFFSET,
+		((gp3_scratch_base + indent) & 0x3FFFFF ) | ((mono_srcx & 7) << 26));
+    WRITE_COMMAND32 (GP3_BLT_WID_HEIGHT, (width << 16) | height);
+    WRITE_COMMAND32 (GP3_BLT_CH3_WIDHI,  (width << 16) | height);
+    WRITE_COMMAND32 (GP3_BLT_BASE_OFFSET, base);
+
+    /* PROGRAM PARAMETERS FOR COLOR SOURCE DATA        */
+	/* Data may be color converted along the way.      */
+	
+	if ((gp3_src_format & GP3_CH3_SRC_MASK) == GP3_CH3_SRC_24BPP_PACKED)
+    {
+        srcoffset  = color_srcx * 3;
+        ch3_offset = 0;
+        size       = width * 3;
+
+        WRITE_COMMAND32 (GP3_BLT_CH3_WIDHI, (((size + 3) >> 2) << 16) | height);
+    }
+    else if (gp3_src_pix_shift == 3)
+	{
+		/* CALCULATE INDENT AND SOURCE OFFSET */
+
+		indent       = (color_srcx >> 1);
+		srcoffset    = (indent & ~3L);
+		indent      &= 3;
+		ch3_offset   = indent | ((color_srcx & 1) << 25);
+
+		size = ((width + (color_srcx & 1) + 1) >> 1) + indent;
+	}
+	else
+	{
+		indent      = (color_srcx << gp3_src_pix_shift);
+		srcoffset   = (indent & ~3L);
+		indent     &= 3;
+		ch3_offset  = indent;
+
+		size = (width << gp3_src_pix_shift) + indent;
+	}
+
+    total_dwords  = (size + 3) >> 2;
+	size_dwords   = (total_dwords << 2) + 8;
+	dword_count   = (size >> 2);
+	byte_count    = (size & 3);
+
+	WRITE_COMMAND32 (GP3_BLT_CH3_OFFSET, ch3_offset);
+	WRITE_COMMAND32 (GP3_BLT_CH3_MODE_STR,
+		GP3_CH3_C3EN            |
+		GP3_CH3_HST_SRC_ENABLE  |
+		gp3_src_format          |
+	  ((gp3_blt_flags & CIMGP_BLTFLAGS_PRES_LUT) << 20));
+	WRITE_COMMAND32 (GP3_BLT_MODE, gp3_blt_mode | GP3_BM_SRC_MONO | GP3_BM_SRC_FB);
+
+	/* START THE BLT */
+
+	WRITE_COMMAND32 (GP3_BLT_CMD_HEADER, gp3_cmd_header);
+	WRITE_GP32 (GP3_CMD_WRITE, gp3_cmd_next);
+	gp3_cmd_current = gp3_cmd_next;
+
+	/* WRITE DATA LINE BY LINE */
+		
+	while (height--)
+	{
+		/* UPDATE THE COMMAND POINTER */
+		
+		cim_cmd_ptr = cim_cmd_base_ptr + gp3_cmd_current;
+
+		/* CHECK IF A WRAP WILL BE NEEDED */
+
+		gp3_cmd_next = gp3_cmd_current + size_dwords;
+		if ((gp3_cmd_bottom - gp3_cmd_next) <= GP3_MAX_COMMAND_SIZE)
+		{
+			gp3_cmd_next  = gp3_cmd_top;
+						
+			GP3_WAIT_WRAP(temp);
+			WRITE_COMMAND32 (0, GP3_DATA_LOAD_HDR_TYPE | GP3_DATA_LOAD_HDR_WRAP |
+				GP3_DATA_LOAD_HDR_ENABLE);
+		}
+		else
+		{
+			GP3_WAIT_PRIMITIVE(temp);
+			WRITE_COMMAND32 (0, GP3_DATA_LOAD_HDR_TYPE | GP3_DATA_LOAD_HDR_ENABLE);
+		}
+
+		/* WRITE DWORD COUNT */
+		
+		WRITE_COMMAND32 (4, GP3_CH3_HOST_SOURCE_TYPE | total_dwords);
+
+		/* WRITE COLOR DATA TO THE COMMAND BUFFER */
+
+		WRITE_COMMAND_STRING32 (8, color_data, srcoffset, dword_count);
+		WRITE_COMMAND_STRING8 (8 + (dword_count << 2), color_data,
+			srcoffset + (dword_count << 2), byte_count);
+
+		/* UPDATE COMMAND BUFFER POINTERS */
+		/* We do this before writing the monochrome data because otherwise */
+		/* the GP could throttle the writes to the host source register    */
+		/* waiting for color data.  If the command buffer has not been     */
+		/* updated to load the color data...                               */
+
+		srcoffset += color_pitch;
+		WRITE_GP32 (GP3_CMD_WRITE, gp3_cmd_next);
+		gp3_cmd_current = gp3_cmd_next;
+    }
+}
+
+/*---------------------------------------------------------------------------
+ * gp_screen_to_screen_masked
+ *
+ * This routine performs a screen to screen BLT, using a monochrome mask to
+ * specify source transparency.  The source data is assumed to be in the
+ * current destination format and to not overlap the destination.
+ *-------------------------------------------------------------------------*/
+
+void gp_screen_to_screen_masked (unsigned long dstoffset, unsigned long srcoffset,
+    unsigned long width, unsigned long height, unsigned long mono_srcx,
+    unsigned char *mono_mask, long mono_pitch)
+{
+    unsigned long indent, temp;
+	unsigned long total_dwords, size_dwords;
+	unsigned long dword_count, byte_count;
+	unsigned long srcoff, size;
+    unsigned long i, base;
+    unsigned long flags = 0;
+
+    if (gp3_blt_flags & CIMGP_BLTFLAGS_INVERTMONO)
+        flags = GP3_RM_SOURCE_INVERT;
+
+    /* MONO CALCULATIONS */
+
+    indent    = (mono_srcx >> 3);
+	srcoff    = (indent & ~3L);
+	indent   &= 3;
+
+    size = ((width + (mono_srcx & 7) + 7) >> 3) + indent;
+	total_dwords = (size + 3) >> 2;
+	size_dwords  = (total_dwords << 2) + 8;
+	dword_count  = (size >> 2);
+	byte_count   = (size & 3);
+	
+    base = ((gp3_fb_base << 24) + (gp3_scratch_base & 0xFFC00000)) |
+            (gp3_base_register & ~GP3_BASE_OFFSET_DSTMASK);
+
+    gp3_cmd_header |= GP3_BLT_HDR_RASTER_ENABLE      |
+                      GP3_BLT_HDR_STRIDE_ENABLE      |
+                      GP3_BLT_HDR_DST_OFF_ENABLE     |
+                      GP3_BLT_HDR_WIDHI_ENABLE       |
+                      GP3_BLT_HDR_CH3_STR_ENABLE     |
+                      GP3_BLT_HDR_CH3_OFF_ENABLE     |
+                      GP3_BLT_HDR_CH3_WIDHI_ENABLE   |
+                      GP3_BLT_HDR_BASE_OFFSET_ENABLE |
+                      GP3_BLT_HDR_BLT_MODE_ENABLE;
+
+    WRITE_COMMAND32 (GP3_BLT_RASTER_MODE, GP3_RM_BPPFMT_8888 | 0xCC);
+    WRITE_COMMAND32 (GP3_BLT_STRIDE, (total_dwords << 2));
+    WRITE_COMMAND32 (GP3_BLT_DST_OFFSET, gp3_scratch_base & 0x3FFFFF);
+    WRITE_COMMAND32 (GP3_BLT_WID_HEIGHT, (total_dwords << 16) | height);
+    WRITE_COMMAND32 (GP3_BLT_CH3_WIDHI, (total_dwords << 16) | height);
+    WRITE_COMMAND32 (GP3_BLT_CH3_OFFSET, 0);
+    WRITE_COMMAND32 (GP3_BLT_BASE_OFFSET, base);
+    WRITE_COMMAND32 (GP3_BLT_CH3_MODE_STR,
+        GP3_CH3_C3EN           |
+		GP3_CH3_REPLACE_SOURCE |
+		GP3_CH3_HST_SRC_ENABLE |
+        GP3_CH3_SRC_8_8_8_8    |
+      ((gp3_blt_flags & CIMGP_BLTFLAGS_PRES_LUT) << 20));
+    WRITE_COMMAND32 (GP3_BLT_MODE, 0);
+    WRITE_COMMAND32 (GP3_BLT_CMD_HEADER, gp3_cmd_header);
+
+    /* START THE BLT */
+
+	WRITE_GP32 (GP3_CMD_WRITE, gp3_cmd_next);
+	gp3_cmd_current = gp3_cmd_next;
+
+    for (i = 0; i < height; i++)
+	{
+		/* UPDATE THE COMMAND POINTER */
+		/* The WRITE_COMMANDXX macros use a pointer to the current buffer space. */
+		/* This is created by adding gp3_cmd_current to the base pointer.        */
+
+		cim_cmd_ptr = cim_cmd_base_ptr + gp3_cmd_current;
+
+		/* CHECK IF A WRAP WILL BE NEEDED */
+
+		gp3_cmd_next = gp3_cmd_current + size_dwords;
+		if ((gp3_cmd_bottom - gp3_cmd_next) <= GP3_MAX_COMMAND_SIZE)
+		{
+			gp3_cmd_next  = gp3_cmd_top;
+    		
+			/* WAIT FOR HARDWARE */
+    		
+			GP3_WAIT_WRAP(temp);
+			WRITE_COMMAND32 (0, GP3_DATA_LOAD_HDR_TYPE | GP3_DATA_LOAD_HDR_WRAP |
+				GP3_DATA_LOAD_HDR_ENABLE);
+		}
+		else
+		{
+			/* WAIT FOR AVAILABLE SPACE */
+
+			GP3_WAIT_PRIMITIVE(temp);
+			WRITE_COMMAND32 (0, GP3_DATA_LOAD_HDR_TYPE | GP3_DATA_LOAD_HDR_ENABLE);
+		}
+
+		/* WRITE DWORD COUNT */
+    	
+		WRITE_COMMAND32 (4, GP3_CH3_HOST_SOURCE_TYPE | total_dwords);
+
+		/* WRITE DATA */
+
+		WRITE_COMMAND_STRING32 (8, mono_mask, srcoff, dword_count);
+		WRITE_COMMAND_STRING8 (8 + (dword_count << 2), mono_mask,
+			srcoff + (dword_count << 2), byte_count);
+
+		/* UPDATE POINTERS */
+
+		srcoff += mono_pitch;
+		WRITE_GP32 (GP3_CMD_WRITE, gp3_cmd_next);
+		gp3_cmd_current = gp3_cmd_next;
+	}
+
+    /* SECOND BLT */
+
+    gp_declare_blt (gp3_blt_flags | CIMGP_BLTFLAGS_HAZARD);
+
+    base = ((gp3_fb_base << 24) +  (dstoffset & 0xFFC00000))                          |
+	       ((gp3_fb_base << 14) + (((gp3_scratch_base + indent) & 0xFFC00000) >> 10)) |
+           ((gp3_fb_base << 4)  + ((srcoffset & 0xFFC00000) >> 20));
+
+    gp3_cmd_header |= GP3_BLT_HDR_RASTER_ENABLE      |
+                      GP3_BLT_HDR_STRIDE_ENABLE      |
+		              GP3_BLT_HDR_DST_OFF_ENABLE     |
+					  GP3_BLT_HDR_SRC_OFF_ENABLE     |
+		              GP3_BLT_HDR_WIDHI_ENABLE       |
+					  GP3_BLT_HDR_CH3_STR_ENABLE     |
+					  GP3_BLT_HDR_CH3_WIDHI_ENABLE   |
+					  GP3_BLT_HDR_BASE_OFFSET_ENABLE |
+					  GP3_BLT_HDR_CH3_OFF_ENABLE     |
+					  GP3_BLT_HDR_BLT_MODE_ENABLE;
+
+    /* ENABLE TRANSPARENCY AND PATTERN COPY ROP */
+    /* The monochrome data is used as a mask but is otherwise not involved in */
+    /* the BLT.  The color data is routed through the pattern channel.        */
+
+    WRITE_COMMAND32 (GP3_BLT_RASTER_MODE, gp3_bpp | 0xF0 | GP3_RM_SRC_TRANS | flags);
+    WRITE_COMMAND32 (GP3_BLT_STRIDE, (total_dwords << 18) | gp3_dst_stride);
+    WRITE_COMMAND32 (GP3_BLT_DST_OFFSET, dstoffset & 0x3FFFFF);
+    WRITE_COMMAND32 (GP3_BLT_SRC_OFFSET,
+		((gp3_scratch_base + indent) & 0x3FFFFF ) | ((mono_srcx & 7) << 26));
+    WRITE_COMMAND32 (GP3_BLT_WID_HEIGHT, (width << 16) | height);
+    WRITE_COMMAND32 (GP3_BLT_CH3_WIDHI,  (width << 16) | height);
+    WRITE_COMMAND32 (GP3_BLT_BASE_OFFSET, base);
+
+    /* PROGRAM PARAMETERS FOR COLOR SOURCE DATA  */
+	
+	WRITE_COMMAND32 (GP3_BLT_CH3_OFFSET, srcoffset & 0x3FFFFF);
+	WRITE_COMMAND32 (GP3_BLT_CH3_MODE_STR,
+		GP3_CH3_C3EN            |
+        gp3_ch3_bpp             |
+        gp3_src_stride          |
+	  ((gp3_blt_flags & CIMGP_BLTFLAGS_PRES_LUT) << 20));
+	WRITE_COMMAND32 (GP3_BLT_MODE, gp3_blt_mode | GP3_BM_SRC_MONO | GP3_BM_SRC_FB);
+
+	/* START THE BLT */
+
+	WRITE_COMMAND32 (GP3_BLT_CMD_HEADER, gp3_cmd_header);
+	WRITE_GP32 (GP3_CMD_WRITE, gp3_cmd_next);
+	gp3_cmd_current = gp3_cmd_next;
+}
+
+/*---------------------------------------------------------------------------
+ * gp_bresenham_line
+ *
+ * This routine draws a vector using the specified Bresenham parameters.
+ * Currently this file does not support a routine that accepts the two
+ * endpoints of a vector and calculates the Bresenham parameters.  If it
+ * ever does, this routine is still required for vectors that have been
+ * clipped.
+ *-------------------------------------------------------------------------*/
+
+void gp_bresenham_line (unsigned long dstoffset, unsigned short length,
+	unsigned short initerr, unsigned short axialerr, unsigned short diagerr,
+	unsigned long flags)
+{
+    unsigned long base;
+    long offset;
+
+    /* HANDLE NEGATIVE VECTORS */
+    /* We have to be very careful with vectors that increment negatively   */
+    /* Our framebuffer scheme tries to align the destination of every      */
+    /* BLT or vector to the nearest 4MB-aligned boundary.  This is         */
+    /* necessary because the GP only supports offsets up to 16MB, but the  */
+    /* framebuffer can be over 128MB.  To solve this problem, the GP       */
+    /* base address registers are alignable to 4MB regions.  However, we   */
+    /* cannot simply align the dest offset when the vector goes negative.  */
+    /* The vector offset could underflow, causing the offset to jump from  */
+    /* near 0 to 16MB.  As we cannot accurately determine the last address */
+    /* that will be written in a vector short of walking the algorithm in  */
+    /* software, we do a worst case approximation.                         */
+
+    offset = dstoffset;
+    if (!(flags & CIMGP_POSMAJOR))
+    {
+        if (flags & CIMGP_YMAJOR)
+            offset -= length * gp3_dst_stride;
+        else
+            offset -= (length << gp3_pix_shift);
+
+        if (offset < 0)
+            offset = 0;
+    }
+    if (!(flags & CIMGP_POSMINOR))
+    {
+        if (flags & CIMGP_YMAJOR)
+            offset -= (length << gp3_pix_shift);
+        else
+            offset -= length * gp3_dst_stride;
+
+        if (offset < 0)
+            offset = 0;
+    }
+
+    offset &= 0xFFC00000;
+    dstoffset -= offset;
+
+    base = ((gp3_fb_base << 24) + offset) |
+            (gp3_base_register & ~GP3_BASE_OFFSET_DSTMASK);
+
+    /* ENABLE RELEVANT REGISTERS */
+	/* Note that we always enable and write the channel 3 mode, if only */
+	/* to turn it off.   Cimarron also always writes the base offset    */
+	/* register to allow operation with frame buffers larger than 16MB. */
+
+	gp3_cmd_header |= GP3_VEC_HDR_DST_OFF_ENABLE     |
+		              GP3_VEC_HDR_VEC_ERR_ENABLE     |
+					  GP3_VEC_HDR_VEC_LEN_ENABLE     |
+					  GP3_VEC_HDR_BASE_OFFSET_ENABLE |
+					  GP3_VEC_HDR_CH3_STR_ENABLE     |
+					  GP3_VEC_HDR_VEC_MODE_ENABLE;
+
+	/* WRITE THE REGISTERS COMMON TO ALL PATTERN TYPES */
+	/* The destination base is the frame buffer base plus whatever */
+	/* 4MB segment we happen to be drawing to.                     */
+
+	WRITE_COMMAND32 (GP3_VECTOR_VEC_ERR,
+		(((unsigned long)axialerr << 16) | (unsigned long)diagerr));
+	WRITE_COMMAND32 (GP3_VECTOR_VEC_LEN,
+		(((unsigned long)length << 16)   | (unsigned long)initerr));
+	WRITE_COMMAND32 (GP3_VECTOR_BASE_OFFSET, base);
+	
+	/* CHECK VECTOR PATTERN CASE */
+
+	if (gp3_ch3_pat)
+	{
+		/* SET THE SOLID COLOR */
+		/* The color for vector patterns from channel 3 comes from */
+		/* the regular pattern registers.                          */
+
+		gp3_cmd_header |= GP3_VEC_HDR_PAT_CLR0_ENABLE;
+
+		WRITE_COMMAND32 (GP3_VECTOR_PAT_COLOR_0, gp3_vector_pattern_color);
+
+		/* INITIALIZE CHANNEL 3 PARAMETERS */
+        /* We route the channel 3 output to the old source channel.  If the user */
+        /* sets a ROP that involves source, they will get unexpected results.    */
+
+		WRITE_COMMAND32 (GP3_VECTOR_DST_OFFSET, dstoffset);
+		WRITE_COMMAND32 (GP3_VECTOR_CH3_MODE_STR,
+            GP3_CH3_C3EN | GP3_CH3_REPLACE_SOURCE | GP3_CH3_COLOR_PAT_ENABLE | GP3_CH3_SRC_8_8_8_8);
+	}
+	else
+	{
+		/* DISABLE CHANNEL 3 AND USE NORMAL PATTERN ORIGINS */
+
+		WRITE_COMMAND32 (GP3_VECTOR_CH3_MODE_STR, 0);
+		WRITE_COMMAND32 (GP3_VECTOR_DST_OFFSET, (dstoffset | gp3_pat_origin));
+	}
+	
+	/* START THE VECTOR */
+
+    WRITE_COMMAND32 (GP3_VEC_CMD_HEADER, gp3_cmd_header);
+	WRITE_COMMAND32 (GP3_VECTOR_MODE, (gp3_vec_mode | flags));
+    WRITE_GP32 (GP3_CMD_WRITE, gp3_cmd_next);
+
+    gp3_cmd_current = gp3_cmd_next;
+
+    /* ADD A SECOND VECTOR TO CLEAR THE BYTE ENABLES            */
+    /* We set a transparent pattern to clear the byte enables.  */
+    /* We then restore the previous pattern. (SiBZ #4001)       */
+
+    if (gp3_ch3_pat)
+    {
+        cim_cmd_ptr = cim_cmd_base_ptr + gp3_cmd_current;
+
+        WRITE_COMMAND32 (0, GP3_LUT_HDR_TYPE | GP3_LUT_HDR_DATA_ENABLE);
+	    WRITE_COMMAND32 (4, 0x100);
+	    WRITE_COMMAND32 (8, (1 | GP3_LUT_DATA_TYPE));	
+	    WRITE_COMMAND32 (12, 0);
+
+        /* DUMMY VECTOR */
+        /* We shouldn't need to write anything but vector mode and the length. */
+
+        WRITE_COMMAND32 (16, GP3_VEC_HDR_TYPE | GP3_VEC_HDR_VEC_MODE_ENABLE |
+            GP3_VEC_HDR_VEC_LEN_ENABLE);
+        WRITE_COMMAND32 (16 + GP3_VECTOR_MODE, (gp3_vec_mode | flags));
+        WRITE_COMMAND32 (16 + GP3_VECTOR_VEC_LEN, (1 << 16) | (unsigned long)initerr);
+
+        WRITE_COMMAND32 (16 + GP3_VECTOR_COMMAND_SIZE, GP3_LUT_HDR_TYPE | GP3_LUT_HDR_DATA_ENABLE);
+	    WRITE_COMMAND32 (20 + GP3_VECTOR_COMMAND_SIZE, 0x100);
+	    WRITE_COMMAND32 (24 + GP3_VECTOR_COMMAND_SIZE, (1 | GP3_LUT_DATA_TYPE));	
+	    WRITE_COMMAND32 (28 + GP3_VECTOR_COMMAND_SIZE, gp3_vec_pat);
+
+        gp3_cmd_current += 32 + GP3_VECTOR_COMMAND_SIZE;
+    }
+}
+
+/*---------------------------------------------------------------------------
+ * gp_line_from_endpoints
+ *
+ * This routine draws a vector from a set of rectangular coordinates.  The
+ * rectangle is assumed to use the currently specified destination stride.
+ *-------------------------------------------------------------------------*/
+
+void gp_line_from_endpoints (unsigned long dstoffset, unsigned long x0,
+    unsigned long y0, unsigned long x1, unsigned long y1, int inclusive)
+{
+    unsigned long base;
+    unsigned long length;
+    unsigned long flags;
+    unsigned short initerr, axialerr, diagerr;
+    long dx, dy, dmaj, dmin;
+    long offset;
+
+    /* ADJUST DESTINATION OFFSET BASED ON STARTING COORDINATE */
+
+    dstoffset += (x0 << gp3_pix_shift) + (y0 * gp3_dst_stride);
+
+    /* CALCULATE BRESENHAM TERMS */
+
+    dx = (long)x1 - (long)x0;
+    dy = (long)y1 - (long)y0;
+    if (dx < 0) dx = -dx;
+    if (dy < 0) dy = -dy;
+
+    if (dx >= dy)
+    {
+        dmaj = dx;
+        dmin = dy;
+        flags = 0;
+        if (x1 > x0) flags |= CIMGP_POSMAJOR;
+        if (y1 > y0) flags |= CIMGP_POSMINOR;
+    }
+    else
+    {
+        dmaj = dy;
+        dmin = dx;
+        flags = CIMGP_YMAJOR;
+        if (x1 > x0) flags |= CIMGP_POSMINOR;
+        if (y1 > y0) flags |= CIMGP_POSMAJOR;
+    }
+
+    axialerr = (unsigned short)(dmin << 1);
+    diagerr  = (unsigned short)((dmin-dmaj) << 1);
+    initerr  = (unsigned short)((dmin << 1) - dmaj);
+    if (!(flags & CIMGP_POSMINOR)) initerr--;
+
+    /* CHECK FOR NO WORK */
+
+    if (!dmaj)
+        return;
+
+    /* CHECK INCLUSIVE OR EXCLUSIVE */
+    /* An inclusive line can be accomplished by simply adding 1 to the */
+    /* line length.                                                    */
+
+    length = dmaj;
+    if (inclusive)
+        length++;
+
+    /* HANDLE NEGATIVE VECTORS */
+
+    offset = dstoffset;
+    if (!(flags & CIMGP_POSMAJOR))
+    {
+        if (flags & CIMGP_YMAJOR)
+            offset -= length * gp3_dst_stride;
+        else
+            offset -= (length << gp3_pix_shift);
+
+        if (offset < 0)
+            offset = 0;
+    }
+    if (!(flags & CIMGP_POSMINOR))
+    {
+        if (flags & CIMGP_YMAJOR)
+            offset -= (length << gp3_pix_shift);
+        else
+            offset -= length * gp3_dst_stride;
+
+        if (offset < 0)
+            offset = 0;
+    }
+
+    offset &= 0xFFC00000;
+    dstoffset -= offset;
+
+    base = ((gp3_fb_base << 24) + offset) |
+            (gp3_base_register & ~GP3_BASE_OFFSET_DSTMASK);
+
+    /* ENABLE RELEVANT REGISTERS */
+	/* Note that we always enable and write the channel 3 mode, if only */
+	/* to turn it off.   Cimarron also always writes the base offset    */
+	/* register to allow operation with frame buffers larger than 16MB. */
+
+	gp3_cmd_header |= GP3_VEC_HDR_DST_OFF_ENABLE     |
+		              GP3_VEC_HDR_VEC_ERR_ENABLE     |
+					  GP3_VEC_HDR_VEC_LEN_ENABLE     |
+					  GP3_VEC_HDR_BASE_OFFSET_ENABLE |
+					  GP3_VEC_HDR_CH3_STR_ENABLE     |
+					  GP3_VEC_HDR_VEC_MODE_ENABLE;
+
+	/* WRITE THE REGISTERS COMMON TO ALL PATTERN TYPES */
+	/* The destination base is the frame buffer base plus whatever */
+	/* 4MB segment we happen to be drawing to.                     */
+
+	WRITE_COMMAND32 (GP3_VECTOR_VEC_ERR,
+		(((unsigned long)axialerr << 16) | (unsigned long)diagerr));
+	WRITE_COMMAND32 (GP3_VECTOR_VEC_LEN,
+		(((unsigned long)length << 16)   | (unsigned long)initerr));
+	WRITE_COMMAND32 (GP3_VECTOR_BASE_OFFSET, base);
+	
+	/* CHECK VECTOR PATTERN CASE */
+
+	if (gp3_ch3_pat)
+	{
+		/* SET THE SOLID COLOR */
+		/* The color for vector patterns from channel 3 comes from */
+		/* the regular pattern registers.                          */
+
+		gp3_cmd_header |= GP3_VEC_HDR_PAT_CLR0_ENABLE;
+
+		WRITE_COMMAND32 (GP3_VECTOR_PAT_COLOR_0, gp3_vector_pattern_color);
+
+		/* INITIALIZE CHANNEL 3 PARAMETERS */
+        /* We route the channel 3 output to the old source channel.  If the user */
+        /* sets a ROP that involves source, they will get unexpected results.    */
+
+		WRITE_COMMAND32 (GP3_VECTOR_DST_OFFSET, dstoffset);
+		WRITE_COMMAND32 (GP3_VECTOR_CH3_MODE_STR,
+            GP3_CH3_C3EN | GP3_CH3_REPLACE_SOURCE | GP3_CH3_COLOR_PAT_ENABLE | GP3_CH3_SRC_8_8_8_8);
+	}
+	else
+	{
+		/* DISABLE CHANNEL 3 AND USE NORMAL PATTERN ORIGINS */
+
+		WRITE_COMMAND32 (GP3_VECTOR_CH3_MODE_STR, 0);
+		WRITE_COMMAND32 (GP3_VECTOR_DST_OFFSET, (dstoffset | gp3_pat_origin));
+	}
+	
+	/* START THE VECTOR */
+
+    WRITE_COMMAND32 (GP3_VEC_CMD_HEADER, gp3_cmd_header);
+	WRITE_COMMAND32 (GP3_VECTOR_MODE, (gp3_vec_mode | flags));
+    WRITE_GP32 (GP3_CMD_WRITE, gp3_cmd_next);
+	gp3_cmd_current = gp3_cmd_next;
+
+    /* ADD A SECOND VECTOR TO CLEAR THE BYTE ENABLES            */
+    /* We set a transparent pattern to clear the byte enables.  */
+    /* We then restore the previous pattern.  (SiBZ #4001)      */
+
+    if (gp3_ch3_pat)
+    {
+        cim_cmd_ptr = cim_cmd_base_ptr + gp3_cmd_current;
+
+        WRITE_COMMAND32 (0, GP3_LUT_HDR_TYPE | GP3_LUT_HDR_DATA_ENABLE);
+	    WRITE_COMMAND32 (4, 0x100);
+	    WRITE_COMMAND32 (8, (1 | GP3_LUT_DATA_TYPE));	
+	    WRITE_COMMAND32 (12, 0);
+
+        /* DUMMY VECTOR */
+        /* We shouldn't need to write anything but vector mode and the length. */
+
+        WRITE_COMMAND32 (16, GP3_VEC_HDR_TYPE | GP3_VEC_HDR_VEC_MODE_ENABLE |
+            GP3_VEC_HDR_VEC_LEN_ENABLE);
+        WRITE_COMMAND32 (16 + GP3_VECTOR_MODE, (gp3_vec_mode | flags));
+        WRITE_COMMAND32 (16 + GP3_VECTOR_VEC_LEN, (1 << 16) | (unsigned long)initerr);
+
+        WRITE_COMMAND32 (16 + GP3_VECTOR_COMMAND_SIZE, GP3_LUT_HDR_TYPE | GP3_LUT_HDR_DATA_ENABLE);
+	    WRITE_COMMAND32 (20 + GP3_VECTOR_COMMAND_SIZE, 0x100);
+	    WRITE_COMMAND32 (24 + GP3_VECTOR_COMMAND_SIZE, (1 | GP3_LUT_DATA_TYPE));	
+	    WRITE_COMMAND32 (28 + GP3_VECTOR_COMMAND_SIZE, gp3_vec_pat);
+
+        gp3_cmd_current += 32 + GP3_VECTOR_COMMAND_SIZE;
+    }
+}
+
+/*---------------------------------------------------------------------------
+ * gp_wait_until_idle
+ *
+ * This routine stalls execution until the GP is no longer actively rendering.
+ *-------------------------------------------------------------------------*/
+
+void gp_wait_until_idle (void)
+{
+    unsigned long temp;
+    while (((temp = READ_GP32 (GP3_BLT_STATUS)) & GP3_BS_BLT_BUSY) ||
+            !(temp & GP3_BS_CB_EMPTY))
+    {
+        ;
+    }
+}
+
+/*---------------------------------------------------------------------------
+ * gp_test_blt_busy
+ *-------------------------------------------------------------------------*/
+
+int gp_test_blt_busy (void)
+{
+    unsigned long temp;
+
+    if (((temp = READ_GP32 (GP3_BLT_STATUS)) & GP3_BS_BLT_BUSY) ||
+        !(temp & GP3_BS_CB_EMPTY))
+        return 1;
+	
+    return 0;
+}
+
+/*---------------------------------------------------------------------------
+ * gp_test_blt_pending
+ *-------------------------------------------------------------------------*/
+
+int gp_test_blt_pending (void)
+{
+    if ((READ_GP32 (GP3_BLT_STATUS)) & GP3_BS_BLT_PENDING)
+        return 1;
+	
+    return 0;
+}
+
+/*---------------------------------------------------------------------------
+ * gp_wait_blt_pending
+ *-------------------------------------------------------------------------*/
+
+void gp_wait_blt_pending (void)
+{
+    while ((READ_GP32 (GP3_BLT_STATUS)) & GP3_BS_BLT_PENDING)
+        ;
+}
+
+/*---------------------------------------------------------------------------
+ * gp_save_state
+ *
+ * This routine saves all persistent GP information.
+ *-------------------------------------------------------------------------*/
+
+void gp_save_state (GP_SAVE_RESTORE *gp_state)
+{
+    Q_WORD msr_value;
+
+    gp_wait_until_idle();
+
+    msr_read64 (MSR_DEVICE_GEODELX_GP, MSR_GEODELINK_CONFIG, &msr_value);
+    gp_state->cmd_bottom  = READ_GP32 (GP3_CMD_BOT) & 0xFFFFFF;
+    gp_state->cmd_top     = READ_GP32 (GP3_CMD_TOP) & 0xFFFFFF;
+    gp_state->cmd_base    = (msr_value.low << 4) & 0xFFF00000;
+    gp_state->base_offset = READ_GP32 (GP3_BASE_OFFSET);
+
+    /* RESET THE READ POINTER */
+
+    gp_set_command_buffer_base (gp_state->cmd_base, gp_state->cmd_top, gp_state->cmd_bottom);
+}
+
+/*---------------------------------------------------------------------------
+ * gp_restore_state
+ *
+ * This routine restores all persistent GP information.
+ *-------------------------------------------------------------------------*/
+
+void gp_restore_state (GP_SAVE_RESTORE *gp_state)
+{
+    gp_wait_until_idle();
+
+    WRITE_GP32 (GP3_BASE_OFFSET, gp_state->base_offset);
+
+    gp_set_command_buffer_base (gp_state->cmd_base, gp_state->cmd_top, gp_state->cmd_bottom);
+}
diff --git a/lib/cimarron/cim/cim_init.c b/lib/cimarron/cim/cim_init.c
new file mode 100644
index 0000000..837a5f1
--- /dev/null
+++ b/lib/cimarron/cim/cim_init.c
@@ -0,0 +1,209 @@
+ /*
+  * <LIC_AMD_STD>
+  * Copyright (C) 2005 Advanced Micro Devices, Inc.  All Rights Reserved.
+  * </LIC_AMD_STD>
+  *
+  * <CTL_AMD_STD>
+  * </CTL_AMD_STD>
+  *
+  * <DOC_AMD_STD>
+  * Cimarron initialization routines.  These routines detect a Geode LX and read
+  * all hardware base addresses.
+  * </DOC_AMD_STD>
+  *
+  */
+
+CIMARRON_STATIC unsigned long init_video_base = 0x80000900;
+
+/*---------------------------------------------------------------------------
+ * init_detect_cpu
+ *
+ * This routine verifies that a Geode LX is present and returns the processor revision
+ * ID.  For compatibility, this routine can also detect a Redcloud processor.
+ *     bits[24:16] = minor version
+ *     bits[15:8]  = major version
+ *     bits[7:0]   = type (1 = Geode GX, 2 = Geode LX)
+ *---------------------------------------------------------------------------*/
+
+int init_detect_cpu (unsigned long *cpu_revision, unsigned long *companion_revision)
+{
+	unsigned long bus, device, i;
+    unsigned long cpu_bus = 0, cpu_device = 0;
+	unsigned long address, data;
+	unsigned long num_bars, function;
+    int cpu_found, sb_found;
+	Q_WORD msr_value;
+
+	/* SEARCH THROUGH PCI BUS                                          */
+	/* We search the PCI bus for the Geode LX or Geode GX northbridge. */
+    /* We then verify that one of its functions is the graphics        */
+    /* controller and that all bars are filled in.                     */	
+	
+    cpu_found = sb_found = 0;
+	for (bus = 0; bus < 256; bus++)
+	{
+		for (device = 0; device < 21; device++)
+		{
+			address = 0x80000000 | (bus << 16) | (device << 11);
+
+			data = init_read_pci (address);
+
+			if (data == PCI_VENDOR_DEVICE_GEODEGX || data == PCI_VENDOR_DEVICE_GEODELX)
+            {
+                cpu_found = 1;
+                cpu_device = device;
+                cpu_bus = bus;
+                if (data == PCI_VENDOR_DEVICE_GEODEGX)
+		            *cpu_revision = CIM_CPU_GEODEGX;
+	            else
+		            *cpu_revision = CIM_CPU_GEODELX;
+            }
+            else if (data == PCI_VENDOR_5535 || data == PCI_VENDOR_5536)
+            {
+                sb_found = 1;
+                if (data == PCI_VENDOR_5535)
+		            *companion_revision = CIM_SB_5535;
+	            else
+		            *companion_revision = CIM_SB_5536;
+            }
+
+            if (cpu_found && sb_found)
+				break;
+		}
+		if (device != 21)
+			break;
+	}
+
+	if (bus == 256)
+	{
+		*cpu_revision = 0;
+		return CIM_STATUS_CPUNOTFOUND;
+	}
+		
+	msr_init_table();
+				
+	if (msr_read64 (MSR_DEVICE_GEODELX_GLCP, GLCP_REVID, &msr_value) != CIM_STATUS_OK)
+	{
+		*cpu_revision = 0;
+		return CIM_STATUS_CPUNOTFOUND;
+	}
+
+	*cpu_revision |= ((msr_value.low & 0xF0) << 4) |
+		             ((msr_value.low & 0x0F) << 16);
+
+    if (msr_read64 (MSR_DEVICE_5535_GLCP, GLCP_REVID, &msr_value) != CIM_STATUS_OK)
+	{
+		*cpu_revision = 0;
+		return CIM_STATUS_CPUNOTFOUND;
+	}
+
+	*companion_revision |= ((msr_value.low & 0xF0) << 4) |
+		                   ((msr_value.low & 0x0F) << 16);
+
+	/* SEARCH ALL FUNCTIONS FOR INTEGRATED GRAPHICS */
+
+    num_bars = 0;
+	for (function = 0; function < 7; function++)
+	{
+		address = 0x80000000 | (cpu_bus << 16) | (cpu_device << 11) | (function << 8);
+		data = init_read_pci (address);
+
+		if (data == PCI_VENDOR_DEVICE_GEODEGX_VIDEO)
+		{
+			num_bars = 4;
+			break;
+		}
+		else if (data == PCI_VENDOR_DEVICE_GEODELX_VIDEO)
+		{
+			num_bars = 5;
+			break;
+		}
+	}
+
+	/* VERIFY THAT ALL BARS ARE PRESENT */
+
+	if (function == 7)
+		return CIM_STATUS_DISPLAYUNAVAILABLE;
+
+	for (i = 0; i < num_bars; i++)
+	{
+		data = init_read_pci (address + 0x10 + (i << 2));
+
+		if (data == 0 || data == 0xFFFFFFFF)
+			break;
+	}
+
+	if (i != num_bars)
+		return CIM_STATUS_DISPLAYUNAVAILABLE;
+	
+	/* SAVE VIDEO BASE ADDRESS FOR FUTURE CALLS */
+
+	init_video_base = address;
+
+	return CIM_STATUS_OK;
+}
+
+/*---------------------------------------------------------------------------
+ * init_read_pci
+ *
+ * This routine reads an unsigned long value from a PCI address.
+ *---------------------------------------------------------------------------*/
+
+unsigned long init_read_pci	(unsigned long address)
+{	
+	OUTD (0xCF8, address);
+	return IND (0xCFC);
+}
+
+/*---------------------------------------------------------------------------
+ * init_read_base_addresses
+ *
+ * This routine reads all base addresses for the peripherals from the PCI BARs.
+ *---------------------------------------------------------------------------*/
+
+int init_read_base_addresses (INIT_BASE_ADDRESSES *base_addresses)
+{
+	unsigned long value;
+
+	/* READ ALL BASE ADDRESSES */
+	
+	base_addresses->framebuffer_base  = init_read_pci (init_video_base + 0x10);
+	base_addresses->gp_register_base  = init_read_pci (init_video_base + 0x14);
+	base_addresses->vg_register_base  = init_read_pci (init_video_base + 0x18);
+	base_addresses->df_register_base  = init_read_pci (init_video_base + 0x1C);
+	base_addresses->vip_register_base = init_read_pci (init_video_base + 0x20);
+	
+	/* READ FRAME BUFFER SIZE */
+	/* The frame buffer size is reported by a VSM in VSA II */
+	/* Virtual Register Class    = 0x02                    */
+	/* VG_MEM_SIZE (1MB units)   = 0x00                    */
+
+	OUTW (0xAC1C, 0xFC53);
+	OUTW (0xAC1C, 0x0200);
+
+	value = (unsigned long)(INW (0xAC1E)) & 0xFE;
+
+	base_addresses->framebuffer_size = value << 20;
+
+	return CIM_STATUS_OK;
+}
+
+/*---------------------------------------------------------------------------
+ * init_read_cpu_frequency
+ *
+ * This routine returns the current CPU core frequency, in MHz.
+ *---------------------------------------------------------------------------*/
+
+int init_read_cpu_frequency (unsigned long *cpu_frequency)
+{
+	/* CPU SPEED IS REPORTED BY A VSM IN VSA II */
+	/* Virtual Register Class = 0x12 (Sysinfo)  */
+	/* CPU Speed Register     = 0x01            */
+
+	OUTW (0xAC1C, 0xFC53);
+	OUTW (0xAC1C, 0x1201);
+
+	*cpu_frequency = (unsigned long)(INW (0xAC1E));
+
+	return CIM_STATUS_OK;
+}
diff --git a/lib/cimarron/cim/cim_modes.c b/lib/cimarron/cim/cim_modes.c
new file mode 100644
index 0000000..cb0f954
--- /dev/null
+++ b/lib/cimarron/cim/cim_modes.c
@@ -0,0 +1,1822 @@
+ /*
+  * <LIC_AMD_STD>
+  * Copyright (C) 2005 Advanced Micro Devices, Inc.  All Rights Reserved.
+  * </LIC_AMD_STD>
+  *
+  * <CTL_AMD_STD>
+  * </CTL_AMD_STD>
+  *
+  * <DOC_AMD_STD>
+  * Cimarron mode tables.
+  * </DOC_AMD_STD>
+  *
+  */
+
+/*-------------------------------*/
+/*  PREDEFINED DISPLAY TIMINGS   */
+/*-------------------------------*/
+
+VG_DISPLAY_MODE CimarronDisplayModes[] =
+{
+    /* 320 x 240 PANEL */
+
+	{ VG_SUPPORTFLAG_75HZ  |                                       /* refresh rate = 75    */
+	  VG_SUPPORTFLAG_8BPP  | VG_SUPPORTFLAG_12BPP |
+      VG_SUPPORTFLAG_15BPP | VG_SUPPORTFLAG_16BPP |
+      VG_SUPPORTFLAG_24BPP | VG_SUPPORTFLAG_32BPP |                /* All BPP supported.   */
+	  VG_SUPPORTFLAG_PANEL,                                        /* Panel Mode.          */
+      VG_MODEFLAG_LOW_BAND |                                       /* Low bandwidth mode.  */
+      VG_MODEFLAG_PANELOUT |                                       /* Panel output.        */
+      VG_MODEFLAG_NEG_HSYNC | VG_MODEFLAG_NEG_VSYNC |			   /* negative syncs       */
+	  VG_MODEFLAG_QVGA,                                            /* QVGA Panel size.     */
+	  320, 240,                                                    /* No scaling.          */
+	  320, 240,                                                    /* 320x240 active       */
+	  320, 240,                                                    /* 320x240 panel        */
+      0, 0, 0, 0, 0,                                               /* No panel registers   */
+	  0x0140, 0x0148, 0x0162, 0x0180, 0x0188, 0x0190,              /* horizontal timings   */
+	  0x00F0, 0x00F4, 0x00F9, 0x00FD, 0x00FF, 0x0104,              /* vertical timings     */
+	  (31L << 16)  | ((2000L * 65536L) / 10000L),                  /* freq = 31.2000 MHz    */
+	},
+
+	/* 640 x 400 */
+
+	{ VG_SUPPORTFLAG_70HZ  |                                       /* refresh rate = 60    */
+	  VG_SUPPORTFLAG_8BPP  | VG_SUPPORTFLAG_12BPP |
+      VG_SUPPORTFLAG_15BPP | VG_SUPPORTFLAG_16BPP |
+      VG_SUPPORTFLAG_24BPP | VG_SUPPORTFLAG_32BPP,                 /* All BPP supported.   */
+	  VG_MODEFLAG_LOW_BAND |                                       /* Low bandwidth mode.  */
+      VG_MODEFLAG_NEG_HSYNC,			                           /* negative HSYNC       */
+	  640, 400,                                                    /* No scaling.          */
+	  0, 0,                                                        /* No mode dimensions.  */
+	  0, 0,                                                        /* No panel dimensions. */
+      0, 0, 0, 0, 0,                                               /* No panel registers   */
+	  0x280, 0x288, 0x290, 0x2F0, 0x318, 0x320,     	           /* horizontal timings   */
+	  0x190, 0x197, 0x19C, 0x19E, 0x1BA, 0x1C1,                    /* vertical timings     */
+      0, 0, 0, 0, 0, 0,                                            /* No even timings      */
+	  (25L << 16) | ((1750L * 65536L) / 10000L),                   /* freq = 25.175 MHz    */
+	},
+
+	/* 640x480 */
+
+	{ VG_SUPPORTFLAG_60HZ  |									   /* refresh rate = 60    */
+	  VG_SUPPORTFLAG_8BPP  | VG_SUPPORTFLAG_12BPP |
+      VG_SUPPORTFLAG_15BPP | VG_SUPPORTFLAG_16BPP |
+      VG_SUPPORTFLAG_24BPP | VG_SUPPORTFLAG_32BPP,                 /* All BPP supported.   */
+	  VG_MODEFLAG_LOW_BAND |                                       /* Low bandwidth mode.  */
+      VG_MODEFLAG_NEG_HSYNC | VG_MODEFLAG_NEG_VSYNC,			   /* negative syncs       */
+	  640, 480,                                                    /* No scaling.          */
+	  0, 0,                                                        /* No mode dimensions.  */
+	  0, 0,                                                        /* No panel dimensions. */
+      0, 0, 0, 0, 0,                                               /* No panel registers   */
+	  0x0280, 0x0288, 0x0290, 0x02E8, 0x0318, 0x0320,	           /* horizontal timings   */
+	  0x01E0, 0x01E8, 0x01EA, 0x01EC, 0x0205, 0x020D,              /* vertical timings     */
+	  0, 0, 0, 0, 0, 0,                                            /* No even timings      */
+      (25L << 16) | ((1750L * 65536L) / 10000L),                   /* freq = 25.175 MHz    */
+	},
+
+    { VG_SUPPORTFLAG_70HZ  |									   /* refresh rate = 70    */
+	  VG_SUPPORTFLAG_8BPP  | VG_SUPPORTFLAG_12BPP |
+      VG_SUPPORTFLAG_15BPP | VG_SUPPORTFLAG_16BPP |
+      VG_SUPPORTFLAG_24BPP | VG_SUPPORTFLAG_32BPP,                 /* All BPP supported.   */
+	  VG_MODEFLAG_LOW_BAND |                                       /* Low bandwidth mode.  */
+      0,
+      640, 480,                                                    /* No scaling.          */
+	  0, 0,                                                        /* No mode dimensions.  */
+	  0, 0,                                                        /* No panel dimensions. */
+      0, 0, 0, 0, 0,                                               /* No panel registers   */
+	  0x0280, 0x0280, 0x0298, 0x02D8, 0x0330, 0x0330,	           /* horizontal timings   */
+	  0x01E0, 0x01E0, 0x01E2, 0x01E5, 0x01F4, 0x01F4,              /* vertical timings     */
+      0, 0, 0, 0, 0, 0,                                            /* No even timings      */
+	  (28L << 16) | ((5600L * 65536L) / 10000L),                   /* freq = 28.560 MHz    */
+	},
+
+	{ VG_SUPPORTFLAG_72HZ  |									   /* refresh rate = 72    */
+	  VG_SUPPORTFLAG_8BPP  | VG_SUPPORTFLAG_12BPP |
+      VG_SUPPORTFLAG_15BPP | VG_SUPPORTFLAG_16BPP |
+      VG_SUPPORTFLAG_24BPP | VG_SUPPORTFLAG_32BPP,                 /* All BPP supported.   */
+	  VG_MODEFLAG_LOW_BAND |                                       /* Low bandwidth mode.  */
+      VG_MODEFLAG_NEG_HSYNC | VG_MODEFLAG_NEG_VSYNC,			   /* negative syncs       */
+	  640, 480,                                                    /* No scaling.          */
+	  0, 0,                                                        /* No mode dimensions.  */
+	  0, 0,                                                        /* No panel dimensions. */
+      0, 0, 0, 0, 0,                                               /* No panel registers   */
+	  0x0280, 0x0288, 0x0298, 0x02c0, 0x0338, 0x0340,	           /* horizontal timings   */
+	  0x01e0, 0x01e8, 0x01e9, 0x01ec, 0x0200, 0x0208,              /* vertical timings     */
+      0, 0, 0, 0, 0, 0,                                            /* No even timings      */
+	  (31L << 16) | ((5000L * 65536L) / 10000L),                   /* freq = 31.5 MHz      */
+	},
+
+	{ VG_SUPPORTFLAG_75HZ  |								       /* refresh rate = 75    */
+	  VG_SUPPORTFLAG_8BPP  | VG_SUPPORTFLAG_12BPP |
+      VG_SUPPORTFLAG_15BPP | VG_SUPPORTFLAG_16BPP |
+      VG_SUPPORTFLAG_24BPP | VG_SUPPORTFLAG_32BPP,                 /* All BPP supported.   */
+	  VG_MODEFLAG_LOW_BAND |                                       /* Low bandwidth mode.  */
+      VG_MODEFLAG_NEG_HSYNC | VG_MODEFLAG_NEG_VSYNC,               /* negative syncs       */
+	  640, 480,                                                    /* No scaling.          */
+	  0, 0,                                                        /* No mode dimensions.  */
+	  0, 0,                                                        /* No panel dimensions. */
+      0, 0, 0, 0, 0,                                               /* No panel registers   */
+	  0x0280, 0x0280, 0x0290, 0x02D0, 0x0348, 0x0348,	           /* horizontal timings   */
+	  0x01E0, 0x01E0, 0x01E1, 0x01E4, 0x01F4, 0x01F4,	           /* vertical timings     */
+      0, 0, 0, 0, 0, 0,                                            /* No even timings      */
+	  (31L << 16) | ((5000L * 65536L) / 10000L),                   /* freq = 31.5 MHz      */
+	},
+
+	{ VG_SUPPORTFLAG_85HZ  |									   /* refresh rate = 85    */
+	  VG_SUPPORTFLAG_8BPP  | VG_SUPPORTFLAG_12BPP |
+      VG_SUPPORTFLAG_15BPP | VG_SUPPORTFLAG_16BPP |
+      VG_SUPPORTFLAG_24BPP | VG_SUPPORTFLAG_32BPP,                 /* All BPP supported.   */
+	  VG_MODEFLAG_LOW_BAND |                                       /* Low bandwidth mode.  */
+      VG_MODEFLAG_NEG_HSYNC | VG_MODEFLAG_NEG_VSYNC,			   /* negative syncs       */
+	  640, 480,                                                    /* No scaling.          */
+	  0, 0,                                                        /* No mode dimensions.  */
+	  0, 0,                                                        /* No panel dimensions. */
+      0, 0, 0, 0, 0,                                               /* No panel registers   */
+	  0x0280, 0x0280, 0x02B8, 0x02F0, 0x0340, 0x0340,              /* horizontal timings   */
+	  0x01E0, 0x01E0, 0x01E1, 0x01E4, 0x01FD, 0x01FD,              /* vertical timings     */
+      0, 0, 0, 0, 0, 0,                                            /* No even timings      */
+	  (36L << 16) | ((0000L * 65536L) / 10000L),                   /* freq = 36.0 MHz      */
+	},
+
+    { VG_SUPPORTFLAG_90HZ  |									   /* refresh rate = 90    */
+	  VG_SUPPORTFLAG_8BPP  | VG_SUPPORTFLAG_12BPP |
+      VG_SUPPORTFLAG_15BPP | VG_SUPPORTFLAG_16BPP |
+      VG_SUPPORTFLAG_24BPP | VG_SUPPORTFLAG_32BPP,                 /* All BPP supported.   */
+	  VG_MODEFLAG_LOW_BAND |                                       /* Low bandwidth mode.  */
+      0,
+      640, 480,                                                    /* No scaling.          */
+	  0, 0,                                                        /* No mode dimensions.  */
+	  0, 0,                                                        /* No panel dimensions. */
+      0, 0, 0, 0, 0,                                               /* No panel registers   */
+	  0x0280, 0x0280, 0x02A0, 0x02E0, 0x0340, 0x0340,              /* horizontal timings   */
+	  0x01E0, 0x01E0, 0x01E1, 0x01E4, 0x01FA, 0x01FA,              /* vertical timings     */
+      0, 0, 0, 0, 0, 0,                                            /* No even timings      */
+	  (37L << 16) | ((8890L * 65536L) / 10000L),                   /* freq = 37.889 MHz    */
+	},
+
+    { VG_SUPPORTFLAG_100HZ | 									   /* refresh rate = 100   */
+	  VG_SUPPORTFLAG_8BPP  | VG_SUPPORTFLAG_12BPP |
+      VG_SUPPORTFLAG_15BPP | VG_SUPPORTFLAG_16BPP |
+      VG_SUPPORTFLAG_24BPP | VG_SUPPORTFLAG_32BPP,                 /* All BPP supported.   */
+	  VG_MODEFLAG_LOW_BAND |                                       /* Low bandwidth mode.  */
+      0,
+      640, 480,                                                    /* No scaling.          */
+	  0, 0,                                                        /* No mode dimensions.  */
+	  0, 0,                                                        /* No panel dimensions. */
+      0, 0, 0, 0, 0,                                               /* No panel registers   */
+	  0x0280, 0x0280, 0x02A8, 0x02E8, 0x0350, 0x0350,              /* horizontal timings   */
+	  0x01E0, 0x01E0, 0x01E1, 0x01E4, 0x01FD, 0x01FD,              /* vertical timings     */
+      0, 0, 0, 0, 0, 0,                                            /* No even timings      */
+	  (43L << 16) | ((1630L * 65536L) / 10000L),                   /* freq = 43.163 MHz    */
+	},
+
+	/* 640 x 480 PANEL */
+
+	{ VG_SUPPORTFLAG_60HZ  |                                       /* refresh rate = 60    */
+	  VG_SUPPORTFLAG_8BPP  | VG_SUPPORTFLAG_12BPP |
+      VG_SUPPORTFLAG_15BPP | VG_SUPPORTFLAG_16BPP |
+      VG_SUPPORTFLAG_24BPP | VG_SUPPORTFLAG_32BPP |                /* All BPP supported.   */
+	  VG_SUPPORTFLAG_PANEL,                                        /* Panel Mode.          */
+      VG_MODEFLAG_LOW_BAND |                                       /* Low bandwidth mode.  */
+      VG_MODEFLAG_PANELOUT |                                       /* Panel output.        */
+      VG_MODEFLAG_NEG_HSYNC | VG_MODEFLAG_NEG_VSYNC,			   /* negative syncs       */
+	  640, 480,                                                    /* No scaling.          */
+	  640, 480,                                                    /* 640x480 active       */
+	  640, 480,                                                    /* 640x480 panel        */
+      0, 0, 0, 0, 0,                                               /* No panel registers   */
+	  0x0280, 0x0280, 0x0290, 0x02E8, 0x0318, 0x0320,     	       /* horizontal timings   */
+	  0x01E0, 0x01E0, 0x01EA, 0x01EC, 0x0205, 0x020D,              /* vertical timings     */
+      0, 0, 0, 0, 0, 0,                                            /* No even timings      */
+	  (25L << 16) | ((1750L * 65536L) / 10000L),                   /* freq = 25.175 MHz    */
+	},
+
+	/* 800x600 */
+
+	{ VG_SUPPORTFLAG_56HZ  |									       /* refresh rate = 56    */
+	  VG_SUPPORTFLAG_8BPP  | VG_SUPPORTFLAG_12BPP |
+      VG_SUPPORTFLAG_15BPP | VG_SUPPORTFLAG_16BPP |
+      VG_SUPPORTFLAG_24BPP | VG_SUPPORTFLAG_32BPP,                 /* All BPP supported.   */
+	  VG_MODEFLAG_LOW_BAND |                                       /* Low bandwidth mode.  */
+      0,
+      800, 600,                                                    /* No scaling.          */
+	  0, 0,                                                        /* No mode dimensions.  */
+	  0, 0,                                                        /* No panel dimensions. */
+      0, 0, 0, 0, 0,                                               /* No panel registers   */
+	  0x0320, 0x0320, 0x0338, 0x0380, 0x0400, 0x0400,	           /* horizontal timings   */
+	  0x0258, 0x0258, 0x0259, 0x025B, 0x0271, 0x0271,              /* vertical timings     */
+      0, 0, 0, 0, 0, 0,                                            /* No even timings      */
+	  (36L << 16) | ((0000L * 65536L) / 10000L),                   /* freq = 36.0 MHz      */
+	},
+
+	{ VG_SUPPORTFLAG_60HZ  |									   /* refresh rate = 60    */
+	  VG_SUPPORTFLAG_8BPP  | VG_SUPPORTFLAG_12BPP |
+      VG_SUPPORTFLAG_15BPP | VG_SUPPORTFLAG_16BPP |
+      VG_SUPPORTFLAG_24BPP | VG_SUPPORTFLAG_32BPP,                 /* All BPP supported.   */
+	  VG_MODEFLAG_LOW_BAND |                                       /* Low bandwidth mode.  */
+      0,
+      800, 600,                                                    /* No scaling.          */
+	  0, 0,                                                        /* No mode dimensions.  */
+	  0, 0,                                                        /* No panel dimensions. */
+      0, 0, 0, 0, 0,                                               /* No panel registers   */
+	  0x0320, 0x0328, 0x0348, 0x03D0, 0x0418, 0x0420,	           /* horizontal timings   */
+	  0x0258, 0x0258, 0x0259, 0x025D, 0x0274, 0x0274,              /* vertical timings     */
+      0, 0, 0, 0, 0, 0,                                            /* No even timings      */
+	  (40L << 16) | ((0000L * 65536L) / 10000L),                   /* freq = 40.00 MHz     */
+	},
+
+    { VG_SUPPORTFLAG_70HZ  |									   /* refresh rate = 70    */
+	  VG_SUPPORTFLAG_8BPP  | VG_SUPPORTFLAG_12BPP |
+      VG_SUPPORTFLAG_15BPP | VG_SUPPORTFLAG_16BPP |
+      VG_SUPPORTFLAG_24BPP | VG_SUPPORTFLAG_32BPP,                 /* All BPP supported.   */
+	  VG_MODEFLAG_LOW_BAND |                                       /* Low bandwidth mode.  */
+      0,
+      800, 600,                                                    /* No scaling.          */
+	  0, 0,                                                        /* No mode dimensions.  */
+	  0, 0,                                                        /* No panel dimensions. */
+      0, 0, 0, 0, 0,                                               /* No panel registers   */
+	  0x0320, 0x0320, 0x0348, 0x0398, 0x0410, 0x0410,	           /* horizontal timings   */
+	  0x0258, 0x0258, 0x025c, 0x025F, 0x0274, 0x0274,              /* vertical timings     */
+      0, 0, 0, 0, 0, 0,                                            /* No even timings      */
+	  (45L << 16) | ((7200L * 65536L) / 10000L),                   /* freq = 45.72 MHz     */
+	},
+
+	{ VG_SUPPORTFLAG_72HZ  |									   /* refresh rate = 72    */
+	  VG_SUPPORTFLAG_8BPP  | VG_SUPPORTFLAG_12BPP |
+      VG_SUPPORTFLAG_15BPP | VG_SUPPORTFLAG_16BPP |
+      VG_SUPPORTFLAG_24BPP | VG_SUPPORTFLAG_32BPP,                 /* All BPP supported.   */
+	  VG_MODEFLAG_LOW_BAND |                                       /* Low bandwidth mode.  */
+      0,
+      800, 600,                                                    /* No scaling.          */
+	  0, 0,                                                        /* No mode dimensions.  */
+	  0, 0,                                                        /* No panel dimensions. */
+      0, 0, 0, 0, 0,                                               /* No panel registers   */
+	  0x0320, 0x0320, 0x0358, 0x03D0, 0x0410, 0x0410,              /* horizontal timings   */
+	  0x0258, 0x0258, 0x027D, 0x0283, 0x029A, 0x029A,	           /* vertical timings     */
+      0, 0, 0, 0, 0, 0,                                            /* No even timings      */
+	  (49L << 16) | ((5000L * 65536L) / 10000L),                   /* freq = 49.5 MHz      */
+	},
+
+	{ VG_SUPPORTFLAG_75HZ  |									   /* refresh rate = 75    */
+	  VG_SUPPORTFLAG_8BPP  | VG_SUPPORTFLAG_12BPP |
+      VG_SUPPORTFLAG_15BPP | VG_SUPPORTFLAG_16BPP |
+      VG_SUPPORTFLAG_24BPP | VG_SUPPORTFLAG_32BPP,                 /* All BPP supported.   */
+	  VG_MODEFLAG_LOW_BAND |                                       /* Low bandwidth mode.  */
+      0,
+      800, 600,                                                    /* No scaling.          */
+	  0, 0,                                                        /* No mode dimensions.  */
+	  0, 0,                                                        /* No panel dimensions. */
+      0, 0, 0, 0, 0,                                               /* No panel registers   */
+	  0x0320, 0x0320, 0x0330, 0x0380, 0x0420, 0x0420,              /* horizontal timings   */
+	  0x0258, 0x0258, 0x0259, 0x025C, 0x0271, 0x0271,	           /* vertical timings     */
+      0, 0, 0, 0, 0, 0,                                            /* No even timings      */
+	  (49L << 16) | ((5000L * 65536L) / 10000L),                   /* freq = 49.5 MHz      */
+	},
+
+	{ VG_SUPPORTFLAG_85HZ  |									   /* refresh rate = 85    */
+	  VG_SUPPORTFLAG_8BPP  | VG_SUPPORTFLAG_12BPP |
+      VG_SUPPORTFLAG_15BPP | VG_SUPPORTFLAG_16BPP |
+      VG_SUPPORTFLAG_24BPP | VG_SUPPORTFLAG_32BPP,                 /* All BPP supported.   */
+	  VG_MODEFLAG_LOW_BAND |                                       /* Low bandwidth mode.  */
+      0,
+      800, 600,                                                    /* No scaling.          */
+	  0, 0,                                                        /* No mode dimensions.  */
+	  0, 0,                                                        /* No panel dimensions. */
+      0, 0, 0, 0, 0,                                               /* No panel registers   */
+	  0x0320, 0x0320, 0x0340, 0x0380, 0x0418, 0x0418,              /* horizontal timings   */
+	  0x0258, 0x0258, 0x0259, 0x025C, 0x0277, 0x0277,              /* vertical timings     */
+      0, 0, 0, 0, 0, 0,                                            /* No even timings      */
+	  (56L << 16) | ((2500L * 65536L) / 10000L),                   /* freq = 56.25 MHz     */
+	},
+
+    { VG_SUPPORTFLAG_90HZ  |									   /* refresh rate = 90    */
+	  VG_SUPPORTFLAG_8BPP  | VG_SUPPORTFLAG_12BPP |
+      VG_SUPPORTFLAG_15BPP | VG_SUPPORTFLAG_16BPP |
+      VG_SUPPORTFLAG_24BPP | VG_SUPPORTFLAG_32BPP,                 /* All BPP supported.   */
+	  VG_MODEFLAG_LOW_BAND |                                       /* Low bandwidth mode.  */
+      0,
+      800, 600,                                                    /* No scaling.          */
+	  0, 0,                                                        /* No mode dimensions.  */
+	  0, 0,                                                        /* No panel dimensions. */
+      0, 0, 0, 0, 0,                                               /* No panel registers   */
+	  0x0320, 0x0320, 0x0348, 0x03A0, 0x0420, 0x0420,              /* horizontal timings   */
+	  0x0258, 0x0258, 0x0259, 0x025C, 0x0278, 0x0278,              /* vertical timings     */
+      0, 0, 0, 0, 0, 0,                                            /* No even timings      */
+	  (60L << 16) | ((650L * 65536L) / 10000L),                    /* freq = 60.065 MHz    */
+	},
+
+    { VG_SUPPORTFLAG_100HZ |									   /* refresh rate = 100   */
+	  VG_SUPPORTFLAG_8BPP  | VG_SUPPORTFLAG_12BPP |
+      VG_SUPPORTFLAG_15BPP | VG_SUPPORTFLAG_16BPP |
+      VG_SUPPORTFLAG_24BPP | VG_SUPPORTFLAG_32BPP,                 /* All BPP supported.   */
+	  VG_MODEFLAG_LOW_BAND |                                       /* Low bandwidth mode.  */
+      0,
+      800, 600,                                                    /* No scaling.          */
+	  0, 0,                                                        /* No mode dimensions.  */
+	  0, 0,                                                        /* No panel dimensions. */
+      0, 0, 0, 0, 0,                                               /* No panel registers   */
+	  0x0320, 0x0320, 0x0350, 0x03A8, 0x0430, 0x0430,              /* horizontal timings   */
+	  0x0258, 0x0258, 0x0259, 0x025C, 0x0277, 0x027C,              /* vertical timings     */
+      0, 0, 0, 0, 0, 0,                                            /* No even timings      */
+	  (68L << 16) | ((1790L * 65536L) / 10000L),                   /* freq = 68.179 MHz    */
+	},
+
+	/* 800x600 PANEL */
+
+	{ VG_SUPPORTFLAG_60HZ  |									   /* refresh rate = 60    */
+	  VG_SUPPORTFLAG_8BPP  | VG_SUPPORTFLAG_12BPP |
+      VG_SUPPORTFLAG_15BPP | VG_SUPPORTFLAG_16BPP |
+      VG_SUPPORTFLAG_24BPP | VG_SUPPORTFLAG_32BPP |                /* All BPP supported.   */
+	  VG_SUPPORTFLAG_PANEL,                                        /* Panel Mode.          */
+	  VG_MODEFLAG_LOW_BAND |                                       /* Low bandwidth mode.  */
+      VG_MODEFLAG_PANELOUT |                                       /* Panel output.        */
+      VG_MODEFLAG_NEG_HSYNC | VG_MODEFLAG_NEG_VSYNC,			   /* negative syncs       */
+	  800, 600,                                                    /* No scaling.          */
+	  800, 600,                                                    /* 800x600 active.      */
+	  800, 600,                                                    /* 800x600 panel        */
+      0, 0, 0, 0, 0,                                               /* No panel registers   */
+	  0x0320, 0x0320, 0x0348, 0x03C8, 0x0420, 0x0420,	           /* horizontal timings   */
+	  0x0258, 0x0258, 0x0259, 0x025D, 0x0274, 0x0274,              /* vertical timings     */
+      0, 0, 0, 0, 0, 0,                                            /* No even timings      */
+	  (40L << 16) | ((0000L * 65536L) / 10000L),                   /* freq = 40.00 MHz     */
+	},
+
+	/* 1024x768 */
+
+	{ VG_SUPPORTFLAG_60HZ  |									   /* refresh rate = 60    */
+	  VG_SUPPORTFLAG_8BPP  | VG_SUPPORTFLAG_12BPP |
+      VG_SUPPORTFLAG_15BPP | VG_SUPPORTFLAG_16BPP |
+      VG_SUPPORTFLAG_24BPP | VG_SUPPORTFLAG_32BPP,                 /* All BPP supported.   */
+	  VG_MODEFLAG_AVG_BAND |                                       /* Avg bandwidth mode.  */
+      VG_MODEFLAG_NEG_HSYNC | VG_MODEFLAG_NEG_VSYNC,			   /* negative syncs       */
+	  1024, 768,                                                   /* No scaling.          */
+	  0, 0,                                                        /* No mode dimensions.  */
+	  0, 0,                                                        /* No panel dimensions. */
+      0, 0, 0, 0, 0,                                               /* No panel registers   */
+	  0x0400, 0x0400, 0x0418, 0x04A0, 0x0540, 0x0540,	           /* horizontal timings   */
+	  0x0300, 0x0300, 0x0303, 0x0309, 0x0326, 0x0326,              /* vertical timings     */
+      0, 0, 0, 0, 0, 0,                                            /* No even timings      */
+	  (65L << 16) | ((0000L * 65536L) / 10000L),                   /* freq = 65.00 MHz     */
+	},
+
+	{ VG_SUPPORTFLAG_70HZ  |									   /* refresh rate = 70    */
+	  VG_SUPPORTFLAG_8BPP  | VG_SUPPORTFLAG_12BPP |
+      VG_SUPPORTFLAG_15BPP | VG_SUPPORTFLAG_16BPP |
+      VG_SUPPORTFLAG_24BPP | VG_SUPPORTFLAG_32BPP,                 /* All BPP supported.   */
+	  VG_MODEFLAG_AVG_BAND |                                       /* Avg bandwidth mode.  */
+      VG_MODEFLAG_NEG_HSYNC | VG_MODEFLAG_NEG_VSYNC,			   /* negative syncs       */
+	  1024, 768,                                                   /* No scaling.          */
+	  0, 0,                                                        /* No mode dimensions.  */
+	  0, 0,                                                        /* No panel dimensions. */
+      0, 0, 0, 0, 0,                                               /* No panel registers   */
+	  0x0400, 0x0400, 0x0418, 0x04A0, 0x0530, 0x0530,              /* horizontal timings   */
+	  0x0300, 0x0300, 0x0303, 0x0309, 0x0326, 0x0326,              /* vertical timings     */
+      0, 0, 0, 0, 0, 0,                                            /* No even timings      */
+	  (75L << 16) | ((0000L * 65536L) / 10000L),                   /* freq = 75.0 MHz      */
+	},
+
+    { VG_SUPPORTFLAG_72HZ  |									   /* refresh rate = 72    */
+	  VG_SUPPORTFLAG_8BPP  | VG_SUPPORTFLAG_12BPP |
+      VG_SUPPORTFLAG_15BPP | VG_SUPPORTFLAG_16BPP |
+      VG_SUPPORTFLAG_24BPP | VG_SUPPORTFLAG_32BPP,                 /* All BPP supported.   */
+	  VG_MODEFLAG_AVG_BAND |                                       /* Avg bandwidth mode.  */
+      0,
+      1024, 768,                                                   /* No scaling.          */
+	  0, 0,                                                        /* No mode dimensions.  */
+	  0, 0,                                                        /* No panel dimensions. */
+      0, 0, 0, 0, 0,                                               /* No panel registers   */
+	  0x0400, 0x0400, 0x0438, 0x04A8, 0x0550, 0x0550,              /* horizontal timings   */
+	  0x0300, 0x0300, 0x0304, 0x0307, 0x0324, 0x0324,              /* vertical timings     */
+      0, 0, 0, 0, 0, 0,                                            /* No even timings      */
+	  (78L << 16) | ((7500L * 65536L) / 10000L),                   /* freq = 78.75 MHz     */
+	},
+
+	{ VG_SUPPORTFLAG_75HZ  |								       /* refresh rate = 75    */
+	  VG_SUPPORTFLAG_8BPP  | VG_SUPPORTFLAG_12BPP |
+      VG_SUPPORTFLAG_15BPP | VG_SUPPORTFLAG_16BPP |
+      VG_SUPPORTFLAG_24BPP | VG_SUPPORTFLAG_32BPP,                 /* All BPP supported.   */
+	  VG_MODEFLAG_AVG_BAND |                                       /* Avg bandwidth mode.  */
+      0,
+      1024, 768,                                                   /* No scaling.          */
+	  0, 0,                                                        /* No mode dimensions.  */
+	  0, 0,                                                        /* No panel dimensions. */
+      0, 0, 0, 0, 0,                                               /* No panel registers   */
+	  0x0400, 0x0400, 0x0410, 0x0470, 0x0520, 0x0520,              /* horizontal timings   */
+	  0x0300, 0x0300, 0x0301, 0x0304, 0x0320, 0x0320,              /* vertical timings     */
+      0, 0, 0, 0, 0, 0,                                            /* No even timings      */
+	  (78L << 16) | ((7500L * 65536L) / 10000L),                   /* freq = 78.75 MHz     */
+	},
+
+	{ VG_SUPPORTFLAG_85HZ  |									   /* refresh rate = 85    */
+	  VG_SUPPORTFLAG_8BPP  | VG_SUPPORTFLAG_12BPP |
+      VG_SUPPORTFLAG_15BPP | VG_SUPPORTFLAG_16BPP |
+      VG_SUPPORTFLAG_24BPP | VG_SUPPORTFLAG_32BPP,                 /* All BPP supported.   */
+	  VG_MODEFLAG_AVG_BAND |                                       /* Avg bandwidth mode.  */
+      0,
+      1024, 768,                                                   /* No scaling.          */
+	  0, 0,                                                        /* No mode dimensions.  */
+	  0, 0,                                                        /* No panel dimensions. */
+      0, 0, 0, 0, 0,                                               /* No panel registers   */
+	  0x0400, 0x0400, 0x0430, 0x0490, 0x0560, 0x0560,              /* horizontal timings   */
+	  0x0300, 0x0300, 0x0301, 0x0304, 0x0328, 0x0328,              /* vertical timings     */
+      0, 0, 0, 0, 0, 0,                                            /* No even timings      */
+	  (94L << 16) | ((5000L * 65536L) / 10000L),                   /* freq = 94.50 MHz     */
+	},
+
+    { VG_SUPPORTFLAG_90HZ  |									   /* refresh rate = 90    */
+	  VG_SUPPORTFLAG_8BPP  | VG_SUPPORTFLAG_12BPP |
+      VG_SUPPORTFLAG_15BPP | VG_SUPPORTFLAG_16BPP |
+      VG_SUPPORTFLAG_24BPP | VG_SUPPORTFLAG_32BPP,                 /* All BPP supported.   */
+	  VG_MODEFLAG_AVG_BAND |                                       /* Avg bandwidth mode.  */
+      0,
+      1024, 768,                                                   /* No scaling.          */
+	  0, 0,                                                        /* No mode dimensions.  */
+	  0, 0,                                                        /* No panel dimensions. */
+      0, 0, 0, 0, 0,                                               /* No panel registers   */
+	  0x0400, 0x0400, 0x0440, 0x04B0, 0x0560, 0x0560,              /* horizontal timings   */
+	  0x0300, 0x0300, 0x0301, 0x0304, 0x0329, 0x0329,              /* vertical timings     */
+      0, 0, 0, 0, 0, 0,                                            /* No even timings      */
+      (100L << 16) | ((1870L * 65536L) / 10000L),                  /* freq = 100.187 MHz   */
+	},
+
+    { VG_SUPPORTFLAG_100HZ |									   /* refresh rate = 100   */
+	  VG_SUPPORTFLAG_8BPP  | VG_SUPPORTFLAG_12BPP |
+      VG_SUPPORTFLAG_15BPP | VG_SUPPORTFLAG_16BPP |
+      VG_SUPPORTFLAG_24BPP | VG_SUPPORTFLAG_32BPP,                 /* All BPP supported.   */
+	  VG_MODEFLAG_AVG_BAND |                                       /* Avg bandwidth mode.  */
+      0,
+      1024, 768,                                                   /* No scaling.          */
+	  0, 0,                                                        /* No mode dimensions.  */
+	  0, 0,                                                        /* No panel dimensions. */
+      0, 0, 0, 0, 0,                                               /* No panel registers   */
+	  0x0400, 0x0400, 0x0448, 0x04B8, 0x0570, 0x0570,              /* horizontal timings   */
+	  0x0300, 0x0300, 0x0301, 0x0304, 0x032E, 0x032E,              /* vertical timings     */
+      0, 0, 0, 0, 0, 0,                                            /* No even timings      */
+	  (113L << 16) | ((3100L * 65536L) / 10000L),                  /* freq = 113.31 MHz    */
+	},
+
+	/* 1024x768 PANEL */
+
+	{ VG_SUPPORTFLAG_60HZ  |									   /* refresh rate = 60    */
+	  VG_SUPPORTFLAG_8BPP  | VG_SUPPORTFLAG_12BPP |
+      VG_SUPPORTFLAG_15BPP | VG_SUPPORTFLAG_16BPP |
+      VG_SUPPORTFLAG_24BPP | VG_SUPPORTFLAG_32BPP |                /* All BPP supported.   */
+	  VG_SUPPORTFLAG_PANEL,                                        /* Panel Mode.          */
+	  VG_MODEFLAG_AVG_BAND |                                       /* Avg bandwidth mode.  */
+      VG_MODEFLAG_PANELOUT |                                       /* Panel output.        */
+      VG_MODEFLAG_NEG_HSYNC | VG_MODEFLAG_NEG_VSYNC,               /* negative syncs       */
+	  1024, 768,                                                   /* No scaling.          */
+	  1024, 768,                                                   /* 1024x768 active.     */
+	  1024, 768,                                                   /* 1024x768 panel       */
+      0, 0, 0, 0, 0,                                               /* No panel registers   */
+	  0x0400, 0x0400, 0x0418, 0x04A0, 0x0540, 0x0540,	           /* horizontal timings   */
+	  0x0300, 0x0300, 0x0303, 0x0309, 0x0326, 0x0326,              /* vertical timings     */
+      0, 0, 0, 0, 0, 0,                                            /* No even timings      */
+	  (65L << 16) | ((0000L * 65536L) / 10000L),                   /* freq = 65.00 MHz     */
+	},
+
+	/* 1152x864 */
+
+    { VG_SUPPORTFLAG_60HZ  |									   /* refresh rate = 60    */
+	  VG_SUPPORTFLAG_8BPP  | VG_SUPPORTFLAG_12BPP |
+      VG_SUPPORTFLAG_15BPP | VG_SUPPORTFLAG_16BPP |
+      VG_SUPPORTFLAG_24BPP | VG_SUPPORTFLAG_32BPP,                 /* All BPP supported.   */
+	  VG_MODEFLAG_AVG_BAND |                                       /* Avg bandwidth mode.  */
+      0,
+      1152, 864,                                                   /* No scaling.          */
+	  0, 0,                                                        /* No mode dimensions.  */
+	  0, 0,                                                        /* No panel dimensions. */
+      0, 0, 0, 0, 0,                                               /* No panel registers   */
+	  0x0480, 0x0480, 0x04C0, 0x0538, 0x05F0, 0x05F0,              /* horizontal timings   */
+      0x0360, 0x0360, 0x0361, 0x0364, 0x037F, 0x037F,              /* vertical timings     */
+      0, 0, 0, 0, 0, 0,                                            /* No even timings      */
+	  (81L << 16)  | ((6000L * 65536L) / 10000L),                  /* freq = 81.60 MHz     */
+	},
+
+    { VG_SUPPORTFLAG_70HZ  |									   /* refresh rate = 70    */
+	  VG_SUPPORTFLAG_8BPP  | VG_SUPPORTFLAG_12BPP |
+      VG_SUPPORTFLAG_15BPP | VG_SUPPORTFLAG_16BPP |
+      VG_SUPPORTFLAG_24BPP | VG_SUPPORTFLAG_32BPP,                 /* All BPP supported.   */
+	  VG_MODEFLAG_AVG_BAND |                                       /* Avg bandwidth mode.  */
+      0,
+      1152, 864,                                                   /* No scaling.          */
+	  0, 0,                                                        /* No mode dimensions.  */
+	  0, 0,                                                        /* No panel dimensions. */
+      0, 0, 0, 0, 0,                                               /* No panel registers   */
+	  0x0480, 0x0480, 0x04C8, 0x0540, 0x0600, 0x0600,              /* horizontal timings   */
+      0x0360, 0x0360, 0x0368, 0x036B, 0x038B, 0x038B,              /* vertical timings     */
+      0, 0, 0, 0, 0, 0,                                            /* No even timings      */
+	  (97L << 16)  | ((5200L * 65536L) / 10000L),                  /* freq = 97.52 MHz     */
+	},
+
+    { VG_SUPPORTFLAG_72HZ  |									   /* refresh rate = 72    */
+	  VG_SUPPORTFLAG_8BPP  | VG_SUPPORTFLAG_12BPP |
+      VG_SUPPORTFLAG_15BPP | VG_SUPPORTFLAG_16BPP |
+      VG_SUPPORTFLAG_24BPP | VG_SUPPORTFLAG_32BPP,                 /* All BPP supported.   */
+	  VG_MODEFLAG_AVG_BAND |                                       /* Avg bandwidth mode.  */
+      0,
+      1152, 864,                                                   /* No scaling.          */
+	  0, 0,                                                        /* No mode dimensions.  */
+	  0, 0,                                                        /* No panel dimensions. */
+      0, 0, 0, 0, 0,                                               /* No panel registers   */
+	  0x0480, 0x0480, 0x04C8, 0x0548, 0x0610, 0x0610,              /* horizontal timings   */
+      0x0360, 0x0360, 0x0367, 0x036A, 0x038B, 0x038B,              /* vertical timings     */
+      0, 0, 0, 0, 0, 0,                                            /* No even timings      */
+	  (101L << 16)  | ((4200L * 65536L) / 10000L),                 /* freq = 101.42 MHz    */
+	},
+
+	{ VG_SUPPORTFLAG_75HZ  |									   /* refresh rate = 75    */
+	  VG_SUPPORTFLAG_8BPP  | VG_SUPPORTFLAG_12BPP |
+      VG_SUPPORTFLAG_15BPP | VG_SUPPORTFLAG_16BPP |
+      VG_SUPPORTFLAG_24BPP | VG_SUPPORTFLAG_32BPP,                 /* All BPP supported.   */
+	  VG_MODEFLAG_AVG_BAND |                                       /* Avg bandwidth mode.  */
+      0,
+      1152, 864,                                                   /* No scaling.          */
+	  0, 0,                                                        /* No mode dimensions.  */
+	  0, 0,                                                        /* No panel dimensions. */
+      0, 0, 0, 0, 0,                                               /* No panel registers   */
+	  0x0480, 0x0480, 0x04C0, 0x0540, 0x0640, 0x0640,              /* horizontal timings   */
+	  0x0360, 0x0360, 0x0361, 0x0364, 0x0384, 0x0384,              /* vertical timings     */
+      0, 0, 0, 0, 0, 0,                                            /* No even timings      */
+	  (108L << 16) | ((0000L * 65536L) / 10000L),                  /* freq = 108.00 MHz    */
+	},
+
+    { VG_SUPPORTFLAG_85HZ  |									   /* refresh rate = 85    */
+	  VG_SUPPORTFLAG_8BPP  | VG_SUPPORTFLAG_12BPP |
+      VG_SUPPORTFLAG_15BPP | VG_SUPPORTFLAG_16BPP |
+      VG_SUPPORTFLAG_24BPP | VG_SUPPORTFLAG_32BPP,                 /* All BPP supported.   */
+	  VG_MODEFLAG_AVG_BAND |                                       /* Avg bandwidth mode.  */
+      0,
+      1152, 864,                                                   /* No scaling.          */
+	  0, 0,                                                        /* No mode dimensions.  */
+	  0, 0,                                                        /* No panel dimensions. */
+      0, 0, 0, 0, 0,                                               /* No panel registers   */
+	  0x0480, 0x0480, 0x04C8, 0x0548, 0x0610, 0x0610,              /* horizontal timings   */
+      0x0360, 0x0360, 0x0363, 0x0366, 0x038B, 0x038B,              /* vertical timings     */
+      0, 0, 0, 0, 0, 0,                                            /* No even timings      */
+	  (119L << 16) | ((6500L * 65536L) / 10000L),                  /* freq = 119.65 MHz    */
+	},
+
+    { VG_SUPPORTFLAG_90HZ  |									   /* refresh rate = 90    */
+	  VG_SUPPORTFLAG_8BPP  | VG_SUPPORTFLAG_12BPP |
+      VG_SUPPORTFLAG_15BPP | VG_SUPPORTFLAG_16BPP |
+      VG_SUPPORTFLAG_24BPP | VG_SUPPORTFLAG_32BPP,                 /* All BPP supported.   */
+	  VG_MODEFLAG_AVG_BAND |                                       /* Avg bandwidth mode.  */
+      0,
+      1152, 864,                                                   /* No scaling.          */
+	  0, 0,                                                        /* No mode dimensions.  */
+	  0, 0,                                                        /* No panel dimensions. */
+      0, 0, 0, 0, 0,                                               /* No panel registers   */
+	  0x0480, 0x0480, 0x04D0, 0x0550, 0x0620, 0x0620,              /* horizontal timings   */
+      0x0360, 0x0360, 0x0369, 0x036C, 0x0396, 0x0396,              /* vertical timings     */
+      0, 0, 0, 0, 0, 0,                                            /* No even timings      */
+	  (129L << 16) | ((6000L * 65536L) / 10000L),                  /* freq = 129.60 MHz    */
+	},
+
+    { VG_SUPPORTFLAG_100HZ  |									   /* refresh rate = 100   */
+	  VG_SUPPORTFLAG_8BPP  | VG_SUPPORTFLAG_12BPP |
+      VG_SUPPORTFLAG_15BPP | VG_SUPPORTFLAG_16BPP |
+      VG_SUPPORTFLAG_24BPP | VG_SUPPORTFLAG_32BPP,                 /* All BPP supported.   */
+	  VG_MODEFLAG_AVG_BAND |                                       /* Avg bandwidth mode.  */
+      0,
+      1152, 864,                                                   /* No scaling.          */
+	  0, 0,                                                        /* No mode dimensions.  */
+	  0, 0,                                                        /* No panel dimensions. */
+      0, 0, 0, 0, 0,                                               /* No panel registers   */
+	  0x0480, 0x0480, 0x04D0, 0x0550, 0x0620, 0x0620,              /* horizontal timings   */
+      0x0360, 0x0360, 0x0363, 0x0366, 0x0396, 0x0396,              /* vertical timings     */
+      0, 0, 0, 0, 0, 0,                                            /* No even timings      */
+	  (144L << 16) | ((0000L * 65536L) / 10000L),                  /* freq = 144.00 MHz    */
+	},
+
+    /* 1152x864 PANEL */
+
+    { VG_SUPPORTFLAG_60HZ  |									   /* refresh rate = 60    */
+	  VG_SUPPORTFLAG_8BPP  | VG_SUPPORTFLAG_12BPP |
+      VG_SUPPORTFLAG_15BPP | VG_SUPPORTFLAG_16BPP |
+      VG_SUPPORTFLAG_24BPP | VG_SUPPORTFLAG_32BPP |                /* All BPP supported.   */
+	  VG_SUPPORTFLAG_PANEL,                                        /* Panel Mode.          */
+	  VG_MODEFLAG_AVG_BAND |                                       /* Avg bandwidth mode.  */
+      VG_MODEFLAG_PANELOUT |                                       /* Panel output.        */
+      VG_MODEFLAG_NEG_HSYNC | VG_MODEFLAG_NEG_VSYNC,			   /* negative syncs       */
+      1152, 864,                                                   /* No scaling.          */
+	  1152, 864,                                                   /* 1152x864 active.     */
+	  1152, 864,                                                   /* 1152x864 panel. */
+      0, 0, 0, 0, 0,                                               /* No panel registers   */
+	  0x0480, 0x0480, 0x04C0, 0x0538, 0x05F0, 0x05F0,              /* horizontal timings   */
+      0x0360, 0x0360, 0x0361, 0x0364, 0x037F, 0x037F,              /* vertical timings     */
+      0, 0, 0, 0, 0, 0,                                            /* No even timings      */
+	  (81L << 16)  | ((6000L * 65536L) / 10000L),                  /* freq = 81.60 MHz     */
+	},
+  		
+	/* 1280x1024 */
+
+	{ VG_SUPPORTFLAG_60HZ  |									   /* refresh rate = 60    */
+	  VG_SUPPORTFLAG_8BPP  | VG_SUPPORTFLAG_12BPP |
+      VG_SUPPORTFLAG_15BPP | VG_SUPPORTFLAG_16BPP |
+      VG_SUPPORTFLAG_24BPP | VG_SUPPORTFLAG_32BPP,                 /* All BPP supported.   */
+	  VG_MODEFLAG_AVG_BAND |                                       /* Avg bandwidth mode.  */
+      0,
+      1280, 1024,                                                  /* No scaling.          */
+	  0, 0,                                                        /* No mode dimensions.  */
+	  0, 0,                                                        /* No panel dimensions. */
+      0, 0, 0, 0, 0,                                               /* No panel registers   */
+	  0x0500, 0x0500, 0x0530, 0x05A0, 0x0698, 0x0698,              /* horizontal timings   */
+	  0x0400, 0x0400, 0x0401, 0x0404, 0x042A, 0x042A,              /* vertical timings     */
+      0, 0, 0, 0, 0, 0,                                            /* No even timings      */
+	  (108L << 16) | ((0000L * 65536L) / 10000L),                  /* freq = 108.00 MHz    */
+	},
+
+    { VG_SUPPORTFLAG_70HZ  |									   /* refresh rate = 70    */
+	  VG_SUPPORTFLAG_8BPP  | VG_SUPPORTFLAG_12BPP |
+      VG_SUPPORTFLAG_15BPP | VG_SUPPORTFLAG_16BPP |
+      VG_SUPPORTFLAG_24BPP | VG_SUPPORTFLAG_32BPP,                 /* All BPP supported.   */
+	  VG_MODEFLAG_AVG_BAND |                                       /* Avg bandwidth mode.  */
+      0,
+      1280, 1024,                                                  /* No scaling.          */
+	  0, 0,                                                        /* No mode dimensions.  */
+	  0, 0,                                                        /* No panel dimensions. */
+      0, 0, 0, 0, 0,                                               /* No panel registers   */
+	  0x0500, 0x0500, 0x0558, 0x05E0, 0x06C0, 0x06C0,              /* horizontal timings   */
+	  0x0400, 0x0400, 0x0406, 0x0409, 0x042F, 0x042F,              /* vertical timings     */
+      0, 0, 0, 0, 0, 0,                                            /* No even timings      */
+	  (129L << 16) | ((6000L * 65536L) / 10000L),                  /* freq = 129.60 MHz    */
+	},
+
+    { VG_SUPPORTFLAG_72HZ  |									   /* refresh rate = 72    */
+	  VG_SUPPORTFLAG_8BPP  | VG_SUPPORTFLAG_12BPP |
+      VG_SUPPORTFLAG_15BPP | VG_SUPPORTFLAG_16BPP |
+      VG_SUPPORTFLAG_24BPP | VG_SUPPORTFLAG_32BPP,                 /* All BPP supported.   */
+	  VG_MODEFLAG_AVG_BAND |                                       /* Avg bandwidth mode.  */
+      0,
+      1280, 1024,                                                  /* No scaling.          */
+	  0, 0,                                                        /* No mode dimensions.  */
+	  0, 0,                                                        /* No panel dimensions. */
+      0, 0, 0, 0, 0,                                               /* No panel registers   */
+	  0x0500, 0x0500, 0x0558, 0x05E0, 0x06C0, 0x06C0,              /* horizontal timings   */
+	  0x0400, 0x0400, 0x0407, 0x040A, 0x0431, 0x0431,              /* vertical timings     */
+      0, 0, 0, 0, 0, 0,                                            /* No even timings      */
+	  (133L << 16) | ((5000L * 65536L) / 10000L),                  /* freq = 133.50 MHz    */
+	},
+
+	{ VG_SUPPORTFLAG_75HZ  |									   /* refresh rate = 75    */
+	  VG_SUPPORTFLAG_8BPP  | VG_SUPPORTFLAG_12BPP |
+      VG_SUPPORTFLAG_15BPP | VG_SUPPORTFLAG_16BPP |
+      VG_SUPPORTFLAG_24BPP | VG_SUPPORTFLAG_32BPP,                 /* All BPP supported.   */
+	  VG_MODEFLAG_AVG_BAND |                                       /* Avg bandwidth mode.  */
+      0,
+      1280, 1024,                                                  /* No scaling.          */
+	  0, 0,                                                        /* No mode dimensions.  */
+	  0, 0,                                                        /* No panel dimensions. */
+      0, 0, 0, 0, 0,                                               /* No panel registers   */
+	  0x0500, 0x0500, 0x0510, 0x05A0, 0x0698, 0x0698,              /* horizontal timings   */
+	  0x0400, 0x0400, 0x0401, 0x0404, 0x042A, 0x042A,              /* vertical timings     */
+      0, 0, 0, 0, 0, 0,                                            /* No even timings      */
+	  (135L << 16) | ((0000L * 65536L) / 10000L),                  /* freq = 135.0 MHz     */
+	},
+
+	{ VG_SUPPORTFLAG_85HZ  |									   /* refresh rate = 85    */
+	  VG_SUPPORTFLAG_8BPP  | VG_SUPPORTFLAG_12BPP |
+      VG_SUPPORTFLAG_15BPP | VG_SUPPORTFLAG_16BPP |
+      VG_SUPPORTFLAG_24BPP | VG_SUPPORTFLAG_32BPP,                 /* All BPP supported.   */
+	  VG_MODEFLAG_AVG_BAND |                                       /* Avg bandwidth mode.  */
+      0,
+      1280, 1024,                                                  /* No scaling.          */
+	  0, 0,                                                        /* No mode dimensions.  */
+	  0, 0,                                                        /* No panel dimensions. */
+      0, 0, 0, 0, 0,                                               /* No panel registers   */
+	  0x0500, 0x0500, 0x0540, 0x05E0, 0x06C0, 0x06C0,              /* horizontal timings   */
+	  0x0400, 0x0400, 0x0401, 0x0404, 0x0430, 0x0430,              /* vertical timings     */
+      0, 0, 0, 0, 0, 0,                                            /* No even timings      */
+	  (157L << 16) | ((5000L * 65536L) / 10000L),                  /* freq = 157.5 MHz     */
+	},
+
+    { VG_SUPPORTFLAG_90HZ  |									   /* refresh rate = 90    */
+	  VG_SUPPORTFLAG_8BPP  | VG_SUPPORTFLAG_12BPP |
+      VG_SUPPORTFLAG_15BPP | VG_SUPPORTFLAG_16BPP |
+      VG_SUPPORTFLAG_24BPP | VG_SUPPORTFLAG_32BPP,                 /* All BPP supported.   */
+	  VG_MODEFLAG_AVG_BAND |                                       /* Avg bandwidth mode.  */
+      0,
+      1280, 1024,                                                  /* No scaling.          */
+	  0, 0,                                                        /* No mode dimensions.  */
+	  0, 0,                                                        /* No panel dimensions. */
+      0, 0, 0, 0, 0,                                               /* No panel registers   */
+	  0x0500, 0x0500, 0x0560, 0x05F0, 0x06E0, 0x06E0,              /* horizontal timings   */
+	  0x0400, 0x0400, 0x040C, 0x040F, 0x0442, 0x0442,              /* vertical timings     */
+      0, 0, 0, 0, 0, 0,                                            /* No even timings      */
+	  (172L << 16) | ((8000L * 65536L) / 10000L),                  /* freq = 172.80 MHz    */
+	},
+
+    { VG_SUPPORTFLAG_100HZ |									   /* refresh rate = 100   */
+	  VG_SUPPORTFLAG_8BPP  | VG_SUPPORTFLAG_12BPP |
+      VG_SUPPORTFLAG_15BPP | VG_SUPPORTFLAG_16BPP |
+      VG_SUPPORTFLAG_24BPP | VG_SUPPORTFLAG_32BPP,                 /* All BPP supported.   */
+	  VG_MODEFLAG_AVG_BAND |                                       /* Avg bandwidth mode.  */
+      0,
+      1280, 1024,                                                  /* No scaling.          */
+	  0, 0,                                                        /* No mode dimensions.  */
+	  0, 0,                                                        /* No panel dimensions. */
+      0, 0, 0, 0, 0,                                               /* No panel registers   */
+	  0x0500, 0x0500, 0x0560, 0x05F0, 0x06E0, 0x06E0,              /* horizontal timings   */
+	  0x0400, 0x0400, 0x0406, 0x0409, 0x0442, 0x0442,              /* vertical timings     */
+      0, 0, 0, 0, 0, 0,                                            /* No even timings      */
+	  (192L << 16) | ((0000L * 65536L) / 10000L),                  /* freq = 192.00 MHz    */
+	},
+
+    /* 1280x1024 PANEL */
+	
+    { VG_SUPPORTFLAG_60HZ  |									   /* refresh rate = 60    */
+	  VG_SUPPORTFLAG_8BPP  | VG_SUPPORTFLAG_12BPP |
+      VG_SUPPORTFLAG_15BPP | VG_SUPPORTFLAG_16BPP |
+      VG_SUPPORTFLAG_24BPP | VG_SUPPORTFLAG_32BPP |                /* All BPP supported.   */
+	  VG_SUPPORTFLAG_PANEL,                                        /* Panel Mode.          */
+	  VG_MODEFLAG_AVG_BAND |                                       /* Avg bandwidth mode.  */
+      VG_MODEFLAG_PANELOUT |                                       /* Panel output.        */
+      VG_MODEFLAG_NEG_HSYNC | VG_MODEFLAG_NEG_VSYNC,			   /* negative syncs       */
+	  1280, 1024,                                                  /* No scaling.          */
+	  1280, 1024,                                                  /* 1280x1024 active.    */
+	  1280, 1024,                                                  /* 1280x1024 panel      */
+      0, 0, 0, 0, 0,                                               /* No panel registers   */
+	  0x0500, 0x0500, 0x0530, 0x05A0, 0x0698, 0x0698,              /* horizontal timings   */
+	  0x0400, 0x0400, 0x0401, 0x0404, 0x042A, 0x042A,              /* vertical timings     */
+      0, 0, 0, 0, 0, 0,                                            /* No even timings      */
+	  (108L << 16) | ((0000L * 65536L) / 10000L),                  /* freq = 108.00 MHz    */
+	},
+
+	/* 1600 x 1200 */
+
+	{ VG_SUPPORTFLAG_60HZ  |                                       /* refresh rate = 60    */
+	  VG_SUPPORTFLAG_8BPP  | VG_SUPPORTFLAG_12BPP |
+      VG_SUPPORTFLAG_15BPP | VG_SUPPORTFLAG_16BPP |
+      VG_SUPPORTFLAG_24BPP | VG_SUPPORTFLAG_32BPP,                 /* All BPP supported.   */
+	  VG_MODEFLAG_HIGH_BAND |                                      /* High bandwidth mode. */
+      0,
+      1600, 1200,                                                  /* No scaling.          */
+	  0, 0,                                                        /* No mode dimensions.  */
+	  0, 0,                                                        /* No panel dimensions. */
+      0, 0, 0, 0, 0,                                               /* No panel registers   */
+	  0x0640, 0x0640, 0x0680, 0x0740, 0x0870, 0x0870,              /* horizontal timings   */
+	  0x04B0, 0x04B0, 0x04B1, 0x04B4, 0x04E2, 0x04E2,              /* vertical timings     */
+      0, 0, 0, 0, 0, 0,                                            /* No even timings      */
+	  (162L << 16) | ((0000L * 65536L) / 10000L),                  /* freq = 162.0 MHz     */
+	},
+
+	{ VG_SUPPORTFLAG_70HZ  |                                       /* refresh rate = 70    */
+	  VG_SUPPORTFLAG_8BPP  | VG_SUPPORTFLAG_12BPP |
+      VG_SUPPORTFLAG_15BPP | VG_SUPPORTFLAG_16BPP |
+      VG_SUPPORTFLAG_24BPP | VG_SUPPORTFLAG_32BPP,                 /* All BPP supported.   */
+	  VG_MODEFLAG_HIGH_BAND |                                      /* High bandwidth mode. */
+      0,
+      1600, 1200,                                                  /* No scaling.          */
+	  0, 0,                                                        /* No mode dimensions.  */
+	  0, 0,                                                        /* No panel dimensions. */
+      0, 0, 0, 0, 0,                                               /* No panel registers   */
+	  0x0640, 0x0640, 0x0680, 0x0740, 0x0870, 0x0870,              /* horizontal timings   */
+	  0x04B0, 0x04B0, 0x04B1, 0x04B4, 0x04E2, 0x04E2,              /* vertical timings     */
+      0, 0, 0, 0, 0, 0,                                            /* No even timings      */
+	  (189L << 16) | ((0000L * 65536L) / 10000L),                  /* freq = 189.0 MHz     */
+	},
+
+    { VG_SUPPORTFLAG_72HZ  |                                       /* refresh rate = 72    */
+	  VG_SUPPORTFLAG_8BPP  | VG_SUPPORTFLAG_12BPP |
+      VG_SUPPORTFLAG_15BPP | VG_SUPPORTFLAG_16BPP |
+      VG_SUPPORTFLAG_24BPP | VG_SUPPORTFLAG_32BPP,                 /* All BPP supported.   */
+	  VG_MODEFLAG_HIGH_BAND |                                      /* High bandwidth mode. */
+      0,
+      1600, 1200,                                                  /* No scaling.          */
+	  0, 0,                                                        /* No mode dimensions.  */
+	  0, 0,                                                        /* No panel dimensions. */
+      0, 0, 0, 0, 0,                                               /* No panel registers   */
+	  0x0640, 0x0640, 0x06B0, 0x0760, 0x0880, 0x0880,              /* horizontal timings   */
+	  0x04B0, 0x04B0, 0x04BD, 0x04C0, 0x04EF, 0x04EF,              /* vertical timings     */
+      0, 0, 0, 0, 0, 0,                                            /* No even timings      */
+	  (198L << 16) | ((0000L * 65536L) / 10000L),                  /* freq = 198.0 MHz     */
+	},
+
+	{ VG_SUPPORTFLAG_75HZ  |                                       /* refresh rate = 75    */
+	  VG_SUPPORTFLAG_8BPP  | VG_SUPPORTFLAG_12BPP |
+      VG_SUPPORTFLAG_15BPP | VG_SUPPORTFLAG_16BPP |
+      VG_SUPPORTFLAG_24BPP | VG_SUPPORTFLAG_32BPP,                 /* All BPP supported.   */
+	  VG_MODEFLAG_HIGH_BAND |                                      /* High bandwidth mode. */
+      0,
+      1600, 1200,                                                  /* No scaling.          */
+	  0, 0,                                                        /* No mode dimensions.  */
+	  0, 0,                                                        /* No panel dimensions. */
+      0, 0, 0, 0, 0,                                               /* No panel registers   */
+	  0x0640, 0x0640, 0x0680, 0x0740, 0x0870, 0x0870,              /* horizontal timings   */
+	  0x04B0, 0x04B0, 0x04B1, 0x04B4, 0x04E2, 0x04E2,              /* vertical timings     */
+      0, 0, 0, 0, 0, 0,                                            /* No even timings      */
+	  (202L << 16) | ((5000L * 65536L) / 10000L),                  /* freq = 202.5 MHz     */
+	},
+
+	{ VG_SUPPORTFLAG_85HZ  |                                       /* refresh rate = 85    */
+	  VG_SUPPORTFLAG_8BPP  | VG_SUPPORTFLAG_12BPP |
+      VG_SUPPORTFLAG_15BPP | VG_SUPPORTFLAG_16BPP |
+      VG_SUPPORTFLAG_24BPP | VG_SUPPORTFLAG_32BPP,                 /* All BPP supported.   */
+	  VG_MODEFLAG_HIGH_BAND |                                      /* High bandwidth mode. */
+      0,
+      1600, 1200,                                                  /* No scaling.          */
+	  0, 0,                                                        /* No mode dimensions.  */
+	  0, 0,                                                        /* No panel dimensions. */
+      0, 0, 0, 0, 0,                                               /* No panel registers   */
+	  0x0640, 0x0640, 0x0680, 0x0740, 0x0870, 0x0870,              /* horizontal timings   */
+	  0x04B0, 0x04B0, 0x04B1, 0x04B4, 0x04E2, 0x04E2,              /* vertical timings     */
+      0, 0, 0, 0, 0, 0,                                            /* No even timings      */
+	  (229L << 16) | ((5000L * 65536L) / 10000L),                  /* freq = 229.5 MHz     */
+	},
+
+    { VG_SUPPORTFLAG_90HZ  |                                       /* refresh rate = 90    */
+	  VG_SUPPORTFLAG_8BPP  | VG_SUPPORTFLAG_12BPP |
+      VG_SUPPORTFLAG_15BPP | VG_SUPPORTFLAG_16BPP |
+      VG_SUPPORTFLAG_24BPP | VG_SUPPORTFLAG_32BPP,                 /* All BPP supported.   */
+	  VG_MODEFLAG_HIGH_BAND |                                      /* High bandwidth mode. */
+      0,
+      1600, 1200,                                                  /* No scaling.          */
+	  0, 0,                                                        /* No mode dimensions.  */
+	  0, 0,                                                        /* No panel dimensions. */
+      0, 0, 0, 0, 0,                                               /* No panel registers   */
+	  0x0640, 0x0640, 0x06C0, 0x0770, 0x08A0, 0x08A0,              /* horizontal timings   */
+	  0x04B0, 0x04B0, 0x04B1, 0x04B4, 0x04F0, 0x04F0,              /* vertical timings     */
+      0, 0, 0, 0, 0, 0,                                            /* No even timings      */
+	  (251L << 16) | ((1820L * 65536L) / 10000L),                  /* freq = 251.182 MHz   */
+	},
+
+    { VG_SUPPORTFLAG_100HZ |                                       /* refresh rate = 100   */
+	  VG_SUPPORTFLAG_8BPP  | VG_SUPPORTFLAG_12BPP |
+      VG_SUPPORTFLAG_15BPP | VG_SUPPORTFLAG_16BPP |
+      VG_SUPPORTFLAG_24BPP | VG_SUPPORTFLAG_32BPP,                 /* All BPP supported.   */
+	  VG_MODEFLAG_HIGH_BAND |                                      /* High bandwidth mode. */
+      0,
+      1600, 1200,                                                  /* No scaling.          */
+	  0, 0,                                                        /* No mode dimensions.  */
+	  0, 0,                                                        /* No panel dimensions. */
+      0, 0, 0, 0, 0,                                               /* No panel registers   */
+	  0x0640, 0x0640, 0x06C0, 0x0770, 0x08A0, 0x08A0,              /* horizontal timings   */
+	  0x04B0, 0x04B0, 0x04B1, 0x04B4, 0x04F7, 0x04F7,              /* vertical timings     */
+      0, 0, 0, 0, 0, 0,                                            /* No even timings      */
+	  (280L << 16) | ((6400L * 65536L) / 10000L),                  /* freq = 280.64 MHz    */
+	},
+
+    /* 1600 x 1200  PANEL */
+
+	{ VG_SUPPORTFLAG_60HZ  |                                       /* refresh rate = 60    */
+	  VG_SUPPORTFLAG_8BPP  | VG_SUPPORTFLAG_12BPP |
+      VG_SUPPORTFLAG_15BPP | VG_SUPPORTFLAG_16BPP |
+      VG_SUPPORTFLAG_24BPP | VG_SUPPORTFLAG_32BPP |                /* All BPP supported.   */
+	  VG_SUPPORTFLAG_PANEL,                                        /* Panel Mode.          */
+      VG_MODEFLAG_HIGH_BAND |                                      /* High bandwidth mode. */
+      VG_MODEFLAG_PANELOUT |                                       /* Panel output.        */
+      VG_MODEFLAG_NEG_HSYNC | VG_MODEFLAG_NEG_VSYNC,			   /* negative syncs       */
+	  1600, 1200,                                                  /* No scaling.          */
+	  1600, 1200,                                                  /* 1600x1200 Active.    */
+	  1600, 1200,                                                  /* 1600x1200 Panel.     */
+      0, 0, 0, 0, 0,                                               /* No panel registers   */
+	  0x0640, 0x0640, 0x0680, 0x0740, 0x0870, 0x0870,              /* horizontal timings   */
+	  0x04B0, 0x04B0, 0x04B1, 0x04B4, 0x04E2, 0x04E2,              /* vertical timings     */
+      0, 0, 0, 0, 0, 0,                                            /* No even timings      */
+	  (162L << 16) | ((0000L * 65536L) / 10000L),                  /* freq = 162.0 MHz     */
+	},
+
+	/* 1920x1440 */
+
+	{ VG_SUPPORTFLAG_60HZ  |                                       /* refresh rate = 60    */
+	  VG_SUPPORTFLAG_8BPP  | VG_SUPPORTFLAG_12BPP |
+      VG_SUPPORTFLAG_15BPP | VG_SUPPORTFLAG_16BPP |
+      VG_SUPPORTFLAG_24BPP | VG_SUPPORTFLAG_32BPP,                 /* All BPP supported.   */
+	  VG_MODEFLAG_HIGH_BAND |                                      /* High bandwidth mode. */
+      0,
+      1920, 1440,                                                  /* No scaling.          */
+	  0, 0,                                                        /* No mode dimensions.  */
+	  0, 0,                                                        /* No panel dimensions. */
+      0, 0, 0, 0, 0,                                               /* No panel registers   */
+	  0x0780, 0x0780, 0x0800, 0x08D0, 0x0A28, 0x0A28,              /* horizontal timings   */
+	  0x05A0, 0x05A0, 0x05A1, 0x05A4, 0x05DC, 0x05DC,              /* vertical timings     */
+      0, 0, 0, 0, 0, 0,                                            /* No even timings      */
+	  (234L << 16) | ((0000L * 65536L) / 10000L),                  /* freq = 234.0 MHz     */
+	},
+
+    { VG_SUPPORTFLAG_70HZ  |                                       /* refresh rate = 70    */
+	  VG_SUPPORTFLAG_8BPP  | VG_SUPPORTFLAG_12BPP |
+      VG_SUPPORTFLAG_15BPP | VG_SUPPORTFLAG_16BPP |
+      VG_SUPPORTFLAG_24BPP | VG_SUPPORTFLAG_32BPP,                 /* All BPP supported.   */
+	  VG_MODEFLAG_HIGH_BAND |                                      /* High bandwidth mode. */
+      0,
+      1920, 1440,                                                  /* No scaling.          */
+	  0, 0,                                                        /* No mode dimensions.  */
+	  0, 0,                                                        /* No panel dimensions. */
+      0, 0, 0, 0, 0,                                               /* No panel registers   */
+	  0x0780, 0x0780, 0x0818, 0x08E8, 0x0A50, 0x0A50,              /* horizontal timings   */
+	  0x05A0, 0x05A0, 0x05A8, 0x05AB, 0x05E2, 0x05E2,              /* vertical timings     */
+      0, 0, 0, 0, 0, 0,                                            /* No even timings      */
+	  (278L << 16) | ((4000L * 65536L) / 10000L),                  /* freq = 278.4 MHz     */
+	},
+
+    { VG_SUPPORTFLAG_72HZ  |                                       /* refresh rate = 70    */
+	  VG_SUPPORTFLAG_8BPP  | VG_SUPPORTFLAG_12BPP |
+      VG_SUPPORTFLAG_15BPP | VG_SUPPORTFLAG_16BPP |
+      VG_SUPPORTFLAG_24BPP | VG_SUPPORTFLAG_32BPP,                 /* All BPP supported.   */
+	  VG_MODEFLAG_HIGH_BAND |                                      /* High bandwidth mode. */
+      0,
+      1920, 1440,                                                  /* No scaling.          */
+	  0, 0,                                                        /* No mode dimensions.  */
+	  0, 0,                                                        /* No panel dimensions. */
+      0, 0, 0, 0, 0,                                               /* No panel registers   */
+	  0x0780, 0x0780, 0x0818, 0x08E8, 0x0A50, 0x0A50,              /* horizontal timings   */
+	  0x05A0, 0x05A0, 0x05A4, 0x05A7, 0x05EB, 0x05EB,              /* vertical timings     */
+      0, 0, 0, 0, 0, 0,                                            /* No even timings      */
+	  (288L << 16) | ((0000L * 65536L) / 10000L),                  /* freq = 288.0 MHz     */
+	},
+
+	{ VG_SUPPORTFLAG_75HZ  |                                       /* refresh rate = 75    */
+	  VG_SUPPORTFLAG_8BPP  | VG_SUPPORTFLAG_12BPP |
+      VG_SUPPORTFLAG_15BPP | VG_SUPPORTFLAG_16BPP |
+      VG_SUPPORTFLAG_24BPP | VG_SUPPORTFLAG_32BPP,                 /* All BPP supported.   */
+	  VG_MODEFLAG_HIGH_BAND |                                      /* High bandwidth mode. */
+      0,
+      1920, 1440,                                                  /* No scaling.          */
+	  0, 0,                                                        /* No mode dimensions.  */
+	  0, 0,                                                        /* No panel dimensions. */
+      0, 0, 0, 0, 0,                                               /* No panel registers   */
+	  0x0780, 0x0780, 0x0810, 0x08F0, 0x0A50, 0x0A50,              /* horizontal timings   */
+	  0x05A0, 0x05A0, 0x05A1, 0x05A4, 0x05DC, 0x05DC,              /* vertical timings     */
+      0, 0, 0, 0, 0, 0,                                            /* No even timings      */
+	  (297L << 16) | ((0000L * 65536L) / 10000L),                  /* freq = 297.0 MHz     */
+	},
+
+	{ VG_SUPPORTFLAG_85HZ  |                                       /* refresh rate = 85    */
+	  VG_SUPPORTFLAG_8BPP  | VG_SUPPORTFLAG_12BPP |
+      VG_SUPPORTFLAG_15BPP | VG_SUPPORTFLAG_16BPP |
+      VG_SUPPORTFLAG_24BPP | VG_SUPPORTFLAG_32BPP,                 /* All BPP supported.   */
+	  VG_MODEFLAG_HIGH_BAND |                                      /* High bandwidth mode. */
+      0,
+      1920, 1440,                                                  /* No scaling.          */
+	  0, 0,                                                        /* No mode dimensions.  */
+	  0, 0,                                                        /* No panel dimensions. */
+      0, 0, 0, 0, 0,                                               /* No panel registers   */
+	  0x0780, 0x0780, 0x0818, 0x08F0, 0x0A60, 0x0A60,              /* horizontal timings   */
+	  0x05A0, 0x05A0, 0x05A1, 0x05A4, 0x05E8, 0x05E8,              /* vertical timings     */
+      0, 0, 0, 0, 0, 0,                                            /* No even timings      */
+	  (341L << 16) | ((3490L * 65536L) / 10000L),                  /* freq = 341.35 MHz    */
+	},
+
+/*-------------------------------*/
+/*     PREDEFINED TV TIMINGS     */
+/*-------------------------------*/
+
+    /* 720 x 480i NTSC */
+
+    { VG_SUPPORTFLAG_60HZ | 									   /* refresh rate = 60    */
+	  VG_SUPPORTFLAG_8BPP  | VG_SUPPORTFLAG_12BPP |
+      VG_SUPPORTFLAG_15BPP | VG_SUPPORTFLAG_16BPP |
+      VG_SUPPORTFLAG_24BPP | VG_SUPPORTFLAG_32BPP |                /* All BPP supported.   */
+      VG_SUPPORTFLAG_NTSC  |                                       /* NTSC Mode.           */
+      VG_SUPPORTFLAG_ADV7171 | VG_SUPPORTFLAG_SAA7127 |
+      VG_SUPPORTFLAG_ADV7300 | VG_SUPPORTFLAG_TVOUT,               /* TV Mode.             */
+      VG_MODEFLAG_LOW_BAND |                                       /* Low bandwidth mode.  */
+      VG_MODEFLAG_INTERLACED | VG_MODEFLAG_TVOUT |                 /* Interlaced TV output */
+	  VG_MODEFLAG_HALFCLOCK |                                      /* DotPLL = 1/2 VOP     */
+      VG_MODEFLAG_INT_FLICKER,                                     /* Flicker Filter Out   */
+      720, 480,                                                    /* No downscaling.      */
+	  0, 0,                                                        /* No mode dimensions.  */
+	  0, 0,                                                        /* No panel dimensions. */
+      0, 0, 0, 0, 0,                                               /* No panel registers   */
+	  0x02D0, 0x02D0, 0x02E1, 0x0320, 0x035A, 0x035A,              /* horizontal timings   */
+	  0x00F0, 0x00F0, 0x00F4, 0x00F8, 0x0107, 0x0107,              /* vertical timings     */
+      0x00F0, 0x00F0, 0x00F4, 0x00F8, 0x0106, 0x0106,              /* Even field timings   */
+	  (27L << 16) | ((0000L * 65536L) / 10000L),                   /* freq = 27.0 MHz      */
+	},
+
+    { VG_SUPPORTFLAG_60HZ | 									   /* refresh rate = 60    */
+	  VG_SUPPORTFLAG_8BPP  | VG_SUPPORTFLAG_12BPP |
+      VG_SUPPORTFLAG_15BPP | VG_SUPPORTFLAG_16BPP |
+      VG_SUPPORTFLAG_24BPP | VG_SUPPORTFLAG_32BPP |                /* All BPP supported.   */
+      VG_SUPPORTFLAG_NTSC  |                                       /* NTSC Mode.           */
+      VG_SUPPORTFLAG_FS454 | VG_SUPPORTFLAG_TVOUT,                 /* TV Mode.             */
+      VG_MODEFLAG_LOW_BAND |                                       /* Low bandwidth mode.  */
+      VG_MODEFLAG_NEG_HSYNC | VG_MODEFLAG_NEG_VSYNC |			   /* negative syncs       */
+      VG_MODEFLAG_PANELOUT | VG_MODEFLAG_INVERT_SHFCLK,            /* TFT Output.          */
+      640, 480,                                                    /* No downscaling.      */
+	  640, 480,                                                    /* 640x480 active.      */
+	  640, 480,                                                    /* 640x480 panel.       */
+      0, 0, 0, 0, 0,                                               /* No panel registers   */
+	  0x0280, 0x0280, 0x0333, 0x0373, 0x03A8, 0x03A8,              /* horizontal timings   */
+	  0x01E0, 0x01E0, 0x01F5, 0x01F7, 0x020D, 0x020D,              /* vertical timings     */
+      0, 0, 0, 0, 0, 0,                                            /* No even timings.     */
+	  (25L << 16) | ((1750L * 65536L) / 10000L),                   /* freq = 25.175 MHz    */
+	},
+
+    /* 800 x 600 NTSC */
+
+    { VG_SUPPORTFLAG_60HZ | 									   /* refresh rate = 60    */
+	  VG_SUPPORTFLAG_8BPP  | VG_SUPPORTFLAG_12BPP |
+      VG_SUPPORTFLAG_15BPP | VG_SUPPORTFLAG_16BPP |
+      VG_SUPPORTFLAG_24BPP | VG_SUPPORTFLAG_32BPP |                /* All BPP supported.   */
+      VG_SUPPORTFLAG_8X6_NTSC |                                    /* 800x600 NTSC.        */
+      VG_SUPPORTFLAG_FS454 | VG_SUPPORTFLAG_TVOUT,                 /* TV Mode.             */
+      VG_MODEFLAG_LOW_BAND |                                       /* Low bandwidth mode.  */
+      VG_MODEFLAG_NEG_HSYNC | VG_MODEFLAG_NEG_VSYNC |			   /* negative syncs       */
+      VG_MODEFLAG_PANELOUT | VG_MODEFLAG_INVERT_SHFCLK,            /* Panel output         */
+      800, 600,                                                    /* No downscaling.      */
+	  800, 600,                                                    /* 800x600 active.      */
+	  800, 600,                                                    /* 800x600 active.      */
+      0, 0, 0, 0, 0,                                               /* No panel registers   */
+	  0x0320, 0x0320, 0x03A7, 0x03E7, 0x03F0, 0x03F0,              /* horizontal timings   */
+      0x0258, 0x0258, 0x026A, 0x0272, 0x028A, 0x028A,              /* vertical timings     */
+	  0, 0, 0, 0, 0, 0,                                            /* No even timings.     */
+      (40L << 16) | ((0000L * 65536L) / 10000L),                   /* freq = 40.000 MHz    */
+	},
+
+    /* 1024 x 768 NTSC */
+
+    { VG_SUPPORTFLAG_60HZ | 									   /* refresh rate = 60    */
+	  VG_SUPPORTFLAG_8BPP  | VG_SUPPORTFLAG_12BPP |
+      VG_SUPPORTFLAG_15BPP | VG_SUPPORTFLAG_16BPP |
+      VG_SUPPORTFLAG_24BPP | VG_SUPPORTFLAG_32BPP |                /* All BPP supported.   */
+      VG_SUPPORTFLAG_10X7_NTSC |                                   /* 1024x768 NTSC.       */
+      VG_SUPPORTFLAG_FS454 | VG_SUPPORTFLAG_TVOUT,                 /* TV Mode.             */
+      VG_MODEFLAG_AVG_BAND |                                       /* Low bandwidth mode.  */
+      VG_MODEFLAG_NEG_HSYNC | VG_MODEFLAG_NEG_VSYNC |			   /* negative syncs       */
+      VG_MODEFLAG_PANELOUT | VG_MODEFLAG_INVERT_SHFCLK,            /* Panel output         */
+      1024, 768,                                                   /* No downscaling.      */
+	  1024, 768,                                                   /* 1024x768 active.     */
+	  1024, 768,                                                   /* 1024x768 active.     */
+      0, 0, 0, 0, 0,                                               /* No panel registers   */
+	  0x0400, 0x0400, 0x0490, 0x04D0, 0x04E0, 0x04E0,              /* horizontal timings   */
+      0x0300, 0x0300, 0x031B, 0x031D, 0x0339, 0x0339,              /* vertical timings     */
+	  0, 0, 0, 0, 0, 0,                                            /* No even timings.     */
+      (65L << 16) | ((0000L * 65536L) / 10000L),                   /* freq = 65.00 MHz     */
+	},
+
+    /* 720 x 576i PAL */
+
+    { VG_SUPPORTFLAG_8BPP  | VG_SUPPORTFLAG_12BPP |
+      VG_SUPPORTFLAG_15BPP | VG_SUPPORTFLAG_16BPP |
+      VG_SUPPORTFLAG_24BPP | VG_SUPPORTFLAG_32BPP |                /* All BPP supported.   */
+      VG_SUPPORTFLAG_PAL   |                                       /* PAL Mode.            */
+      VG_SUPPORTFLAG_ADV7171 | VG_SUPPORTFLAG_SAA7127 |
+      VG_SUPPORTFLAG_ADV7300 | VG_SUPPORTFLAG_TVOUT,               /* TV Mode.             */
+      VG_MODEFLAG_LOW_BAND |                                       /* Low bandwidth mode.  */
+      VG_MODEFLAG_TVOUT | VG_MODEFLAG_INTERLACED |                 /* Interlaced TV out.   */
+      VG_MODEFLAG_HALFCLOCK |                                      /* DotPLL = 1/2 VOP     */
+      VG_MODEFLAG_INT_FLICKER,                                     /* Flicker Filter Out   */
+	  720, 576,                                                    /* No downscaling.      */
+	  0, 0,                                                        /* No mode dimensions.  */
+	  0, 0,                                                        /* No panel dimensions. */
+      0, 0, 0, 0, 0,                                               /* No panel registers   */
+	  0x02D0, 0x02D0, 0x02E4, 0x0324, 0x0360, 0x0360,              /* horizontal timings   */
+	  0x0120, 0x0120, 0x0123, 0x0127, 0x0139, 0x0139,              /* vertical timings     */
+      0x0120, 0x0120, 0x0123, 0x0127, 0x0138, 0x0138,              /* Even timings         */
+	  (27L << 16) | ((0000L * 65536L) / 10000L),                   /* freq = 27.0 MHz      */
+	},
+
+    { VG_SUPPORTFLAG_8BPP  | VG_SUPPORTFLAG_12BPP |
+      VG_SUPPORTFLAG_15BPP | VG_SUPPORTFLAG_16BPP |
+      VG_SUPPORTFLAG_24BPP | VG_SUPPORTFLAG_32BPP |                /* All BPP supported.   */
+      VG_SUPPORTFLAG_PAL   |                                       /* PAL Mode.            */
+      VG_SUPPORTFLAG_FS454 | VG_SUPPORTFLAG_TVOUT,                 /* TV Mode.             */
+      VG_MODEFLAG_LOW_BAND |                                       /* Low bandwidth mode.  */
+      VG_MODEFLAG_NEG_HSYNC | VG_MODEFLAG_NEG_VSYNC |			   /* negative syncs       */
+      VG_MODEFLAG_PANELOUT | VG_MODEFLAG_INVERT_SHFCLK,            /* Panel output.        */
+	  640, 480,                                                    /* No downscaling.      */
+	  640, 480,                                                    /* No mode dimensions.  */
+	  640, 480,                                                    /* 640x480 active.      */
+      0, 0, 0, 0, 0,                                               /* 640x480 panel.       */
+	  0x0280, 0x0280, 0x030F, 0x034F, 0x0360, 0x0360,              /* horizontal timings   */
+	  0x01E0, 0x01E0, 0x01F5, 0x01F7, 0x020D, 0x020D,              /* vertical timings     */
+      0, 0, 0, 0, 0, 0,                                            /* No even timings.     */
+	  (25L << 16) | ((1750L * 65536L) / 10000L),                   /* freq = 25.175 MHz    */
+	},
+
+    /* 800 x 600 PAL */
+
+    { VG_SUPPORTFLAG_60HZ | 									   /* refresh rate = 60    */
+	  VG_SUPPORTFLAG_8BPP  | VG_SUPPORTFLAG_12BPP |
+      VG_SUPPORTFLAG_15BPP | VG_SUPPORTFLAG_16BPP |
+      VG_SUPPORTFLAG_24BPP | VG_SUPPORTFLAG_32BPP |                /* All BPP supported.   */
+      VG_SUPPORTFLAG_8X6_PAL |                                     /* 800x600 PAL.         */
+      VG_SUPPORTFLAG_FS454 | VG_SUPPORTFLAG_TVOUT,                 /* TV Mode.             */
+      VG_MODEFLAG_LOW_BAND |                                       /* Low bandwidth mode.  */
+      VG_MODEFLAG_NEG_HSYNC | VG_MODEFLAG_NEG_VSYNC |			   /* negative syncs       */
+      VG_MODEFLAG_PANELOUT | VG_MODEFLAG_INVERT_SHFCLK,            /* Panel output         */
+      800, 600,                                                    /* No downscaling.      */
+	  800, 600,                                                    /* 800x600 active.      */
+	  800, 600,                                                    /* 800x600 active.      */
+      0, 0, 0, 0, 0,                                               /* No panel registers   */
+	  0x0320, 0x0320, 0x03A7, 0x03E7, 0x03F0, 0x03F0,              /* horizontal timings   */
+      0x0258, 0x0258, 0x0270, 0x0272, 0x028A, 0x028A,              /* vertical timings     */
+	  0, 0, 0, 0, 0, 0,                                            /* No even timings.     */
+      (40L << 16) | ((0000L * 65536L) / 10000L),                   /* freq = 40.000 MHz    */
+	},
+
+    /* 1024 x 768 PAL */
+
+    { VG_SUPPORTFLAG_60HZ | 									   /* refresh rate = 60    */
+	  VG_SUPPORTFLAG_8BPP  | VG_SUPPORTFLAG_12BPP |
+      VG_SUPPORTFLAG_15BPP | VG_SUPPORTFLAG_16BPP |
+      VG_SUPPORTFLAG_24BPP | VG_SUPPORTFLAG_32BPP |                /* All BPP supported.   */
+      VG_SUPPORTFLAG_10X7_PAL |                                    /* 1024x768 NTSC.       */
+      VG_SUPPORTFLAG_FS454 | VG_SUPPORTFLAG_TVOUT,                 /* TV Mode.             */
+      VG_MODEFLAG_AVG_BAND |                                       /* Low bandwidth mode.  */
+      VG_MODEFLAG_NEG_HSYNC | VG_MODEFLAG_NEG_VSYNC |			   /* negative syncs       */
+      VG_MODEFLAG_PANELOUT | VG_MODEFLAG_INVERT_SHFCLK,            /* Panel output         */
+      1024, 768,                                                   /* No downscaling.      */
+	  1024, 768,                                                   /* 1024x768 active.     */
+	  1024, 768,                                                   /* 1024x768 active.     */
+      0, 0, 0, 0, 0,                                               /* No panel registers   */
+	  0x0400, 0x0400, 0x0490, 0x04d0, 0x04e0, 0x04e0,              /* horizontal timings   */
+      0x0300, 0x0300, 0x031b, 0x031d, 0x0339, 0x0339,              /* vertical timings     */
+	  0, 0, 0, 0, 0, 0,                                            /* No even timings.     */
+      (65L << 16) | ((0000L * 65536L) / 10000L),                   /* freq = 65.00 MHz     */
+	},
+
+    /* 720 x 480p HDTV */
+
+    { VG_SUPPORTFLAG_60HZ | 									   /* refresh rate = 60    */
+	  VG_SUPPORTFLAG_8BPP  | VG_SUPPORTFLAG_12BPP |
+      VG_SUPPORTFLAG_15BPP | VG_SUPPORTFLAG_16BPP |
+      VG_SUPPORTFLAG_24BPP | VG_SUPPORTFLAG_32BPP |                /* All BPP supported.   */
+      VG_SUPPORTFLAG_480P  |                                       /* 720x480P.            */
+      VG_SUPPORTFLAG_ADV7300 | VG_SUPPORTFLAG_TVOUT,               /* TV Mode.             */
+      VG_MODEFLAG_LOW_BAND |                                       /* Low bandwidth mode.  */
+      VG_MODEFLAG_TVOUT,                                           /* Progressive TV out.  */
+	  720, 480,                                                    /* No scaling.          */
+	  0, 0,                                                        /* No mode dimensions.  */
+	  0, 0,                                                        /* No panel dimensions. */
+      0, 0, 0, 0, 0,                                               /* No panel registers   */
+	  0x02D0, 0x02D0, 0x02E0, 0x0328, 0x035A, 0x035A,              /* horizontal timings   */
+	  0x01E0, 0x01E0, 0x01E1, 0x01E3, 0x020D, 0x020D,              /* vertical timings     */
+      0, 0, 0, 0, 0, 0,                                            /* No even timings.     */
+	  (27L << 16) | ((0000L * 65536L) / 10000L),                   /* freq = 27.0 MHz      */
+	},
+
+    { VG_SUPPORTFLAG_60HZ | 									   /* refresh rate = 60    */
+	  VG_SUPPORTFLAG_8BPP  | VG_SUPPORTFLAG_12BPP |
+      VG_SUPPORTFLAG_15BPP | VG_SUPPORTFLAG_16BPP |
+      VG_SUPPORTFLAG_24BPP | VG_SUPPORTFLAG_32BPP |                /* All BPP supported.   */
+      VG_SUPPORTFLAG_480P  |                                       /* 720x480P.            */
+      VG_SUPPORTFLAG_FS454 | VG_SUPPORTFLAG_TVOUT,                 /* TV Mode.             */
+      VG_MODEFLAG_LOW_BAND |                                       /* Low bandwidth mode.  */
+      VG_MODEFLAG_PANELOUT | VG_MODEFLAG_INVERT_SHFCLK,            /* Panel output.        */
+	  720, 480,                                                    /* No scaling.          */
+	  720, 480,                                                    /* 720x480 active.      */
+	  720, 480,                                                    /* 720x480 panel.       */
+      0, 0, 0, 0, 0,                                               /* No panel registers   */
+	  0x02D0, 0x02D0, 0x02E3, 0x0323, 0x035A, 0x035A,              /* horizontal timings   */
+	  0x01E0, 0x01E0, 0x01E4, 0x01EA, 0x020D, 0x020D,              /* vertical timings     */
+      0, 0, 0, 0, 0, 0,                                            /* No even timings.     */
+	  (27L << 16) | ((0000L * 65536L) / 10000L),                   /* freq = 27.0 MHz      */
+	},
+
+    /* 1280x720p HDTV */
+
+	{ VG_SUPPORTFLAG_8BPP  | VG_SUPPORTFLAG_12BPP |
+      VG_SUPPORTFLAG_15BPP | VG_SUPPORTFLAG_16BPP |
+      VG_SUPPORTFLAG_24BPP | VG_SUPPORTFLAG_32BPP |                /* All BPP supported.   */
+      VG_SUPPORTFLAG_720P  |                                       /* 1280x720P            */
+      VG_SUPPORTFLAG_ADV7300 | VG_SUPPORTFLAG_TVOUT,               /* TV Mode.             */
+      VG_MODEFLAG_AVG_BAND |                                       /* Avg bandwidth mode.  */
+      VG_MODEFLAG_TVOUT,                                           /* Progressive TV out   */
+	  1280, 720,                                                   /* No scaling.          */
+	  0, 0,                                                        /* No mode dimensions.  */
+	  0, 0,                                                        /* No panel dimensions. */
+      0, 0, 0, 0, 0,                                               /* No panel registers   */
+	  0x0500, 0x0500, 0x0546, 0x0596, 0x0672, 0x0672,              /* horizontal timings   */
+	  0x02D0, 0x02D0, 0x02D3, 0x02D8, 0x02EE, 0x02EE,              /* vertical timings     */
+      0, 0, 0, 0, 0, 0,                                            /* even timings         */
+	  (74L << 16) | ((2500L * 65536L) / 10000L),                   /* freq = 74.25 MHz     */
+	},
+
+    { VG_SUPPORTFLAG_8BPP  | VG_SUPPORTFLAG_12BPP |
+      VG_SUPPORTFLAG_15BPP | VG_SUPPORTFLAG_16BPP |
+      VG_SUPPORTFLAG_24BPP | VG_SUPPORTFLAG_32BPP |                /* All BPP supported.   */
+      VG_SUPPORTFLAG_720P  |                                       /* 1280x720P            */
+      VG_SUPPORTFLAG_FS454 | VG_SUPPORTFLAG_TVOUT,                 /* TV Mode.             */
+      VG_MODEFLAG_AVG_BAND |                                       /* Avg bandwidth mode.  */
+      VG_MODEFLAG_PANELOUT | VG_MODEFLAG_INVERT_SHFCLK,            /* Panel output.        */
+	  1280, 720,                                                   /* No scaling.          */
+	  1280, 720,                                                   /* 1280x720 active.     */
+	  1280, 720,                                                   /* 1280x720 panel.      */
+      0, 0, 0, 0, 0,                                               /* No panel registers   */
+	  0x0500, 0x0500, 0x0547, 0x0597, 0x0672, 0x0672,              /* horizontal timings   */
+	  0x02D0, 0x02D0, 0x02D4, 0x02D9, 0x02EE, 0x02EE,              /* vertical timings     */
+      0, 0, 0, 0, 0, 0,                                            /* No even timings.     */
+	  (74L << 16) | ((2500L * 65536L) / 10000L),                   /* freq = 74.25 MHz     */
+	},
+
+    /* 1920x1080i HDTV */
+
+	{ VG_SUPPORTFLAG_60HZ  |                                       /* refresh rate = 60    */
+	  VG_SUPPORTFLAG_8BPP  | VG_SUPPORTFLAG_12BPP |
+      VG_SUPPORTFLAG_15BPP | VG_SUPPORTFLAG_16BPP |
+      VG_SUPPORTFLAG_24BPP | VG_SUPPORTFLAG_32BPP |                /* All BPP supported.   */
+      VG_SUPPORTFLAG_1080I |                                       /* 1920x1080i Mode.     */
+      VG_SUPPORTFLAG_ADV7300 | VG_SUPPORTFLAG_FS454 |
+      VG_SUPPORTFLAG_TVOUT,                                        /* TV Mode.             */
+	  VG_MODEFLAG_HIGH_BAND |                                      /* High bandwidth mode. */
+      VG_MODEFLAG_INTERLACED | VG_MODEFLAG_TVOUT |                 /* Interlaced TV output */
+      VG_MODEFLAG_INT_ADDRESS | VG_MODEFLAG_INVERT_SHFCLK,         /* Interlaced addressing*/
+	  1920, 1080,                                                  /* 2:1 downscaling.     */
+	  0, 0,                                                        /* No mode dimensions.  */
+	  0, 0,                                                        /* No panel dimensions. */
+      0, 0, 0, 0, 0,                                               /* No panel registers   */
+	  0x0780, 0x0780, 0x07AD, 0x0805, 0x0898, 0x0898,     	       /* horizontal timings   */
+	  0x021C, 0x021C, 0x021E, 0x0226, 0x0233, 0x0233,              /* vertical timings     */
+      0x021C, 0x021C, 0x021E, 0x0226, 0x0232, 0x0232,              /* even field timings   */
+	  (74L << 16) | ((2500L * 65536L) / 10000L),                   /* freq = 74.25 MHz     */
+	},
+};
+
+#define NUM_CIMARRON_DISPLAY_MODES sizeof(CimarronDisplayModes) / sizeof(VG_DISPLAY_MODE)
+
+/*-----------------------------------*/
+/*  PREDEFINED PLL FREQUENCIES       */
+/*-----------------------------------*/
+
+PLL_FREQUENCY CimarronPLLFrequencies[] =
+{
+    { 0x000031AC, (24L << 16)  | ((9230L * 65536L) / 10000L) }, /* 24.9230, - 4,27,13 */
+    { 0x0000215D, (25L << 16)  | ((1750L * 65536L) / 10000L) }, /* 25.1750, - 3,22,14 */
+    { 0x00001087, (27L << 16)  | ((0000L * 65536L) / 10000L) }, /* 27.0000, - 2, 9, 8 */
+    { 0x0000216C, (28L << 16)  | ((3220L * 65536L) / 10000L) }, /* 28.3220, - 3,23,13 */
+    { 0x0000218D, (28L << 16)  | ((5600L * 65536L) / 10000L) }, /* 28.5600, - 3,25,14 */
+    { 0x000010C9, (31L << 16)  | ((2000L * 65536L) / 10000L) }, /* 31.2000, - 2,13,10 */
+    { 0x00003147, (31L << 16)  | ((5000L * 65536L) / 10000L) }, /* 31.5000, - 4,21, 8 */
+    { 0x000010A7, (33L << 16)  | ((320L  * 65536L) / 10000L) }, /* 33.0320, - 2,11, 8 */
+    { 0x00002159, (35L << 16)  | ((1120L * 65536L) / 10000L) }, /* 35.1120, - 3,22,10 */
+    { 0x00004249, (35L << 16)  | ((5000L * 65536L) / 10000L) }, /* 35.5000, - 5,37,10 */
+    { 0x00000057, (36L << 16)  | ((0000L * 65536L) / 10000L) }, /* 36.0000, - 1, 6, 8 */
+    { 0x0000219A, (37L << 16)  | ((8890L * 65536L) / 10000L) }, /* 37.8890, - 3,26,11 */
+    { 0x00002158, (39L << 16)  | ((1680L * 65536L) / 10000L) }, /* 39.1680, - 3,22, 9 */
+    { 0x00000045, (40L << 16)  | ((0000L * 65536L) / 10000L) }, /* 40.0000, - 1, 5, 6 */
+    { 0x00000089, (43L << 16)  | ((1630L * 65536L) / 10000L) }, /* 43.1630, - 1, 9,10 */
+    { 0x000010E7, (44L << 16)  | ((9000L * 65536L) / 10000L) }, /* 44.9000, - 2,15, 8 */
+    { 0x00002136, (45L << 16)  | ((7200L * 65536L) / 10000L) }, /* 45.7200, - 3,20, 7 */
+    { 0x00003207, (49L << 16)  | ((5000L * 65536L) / 10000L) }, /* 49.5000, - 4,33, 8 */
+    { 0x00002187, (50L << 16)  | ((0000L * 65536L) / 10000L) }, /* 50.0000, - 3,25, 8 */
+    { 0x00004286, (56L << 16)  | ((2500L * 65536L) / 10000L) }, /* 56.2500, - 5,41, 7 */
+    { 0x000010E5, (60L << 16)  | ((650L  * 65536L) / 10000L) }, /* 60.0650, - 2,15, 6 */
+    { 0x00004214, (65L << 16)  | ((0000L * 65536L) / 10000L) }, /* 65.0000, - 5,34, 5 */
+    { 0x00001105, (68L << 16)  | ((1790L * 65536L) / 10000L) }, /* 68.1790, - 2,17, 6 */
+    { 0x000031E4, (74L << 16)  | ((2500L * 65536L) / 10000L) }, /* 74.2500, - 4,31, 5 */
+    { 0x00003183, (75L << 16)  | ((0000L * 65536L) / 10000L) }, /* 75.0000, - 4,25, 4 */
+    { 0x00004284, (78L << 16)  | ((7500L * 65536L) / 10000L) }, /* 78.7500, - 5,41, 5 */
+    { 0x00001104, (81L << 16)  | ((6000L * 65536L) / 10000L) }, /* 81.6000, - 2,17, 5 */
+    { 0x00006363, (94L << 16)  | ((5000L * 65536L) / 10000L) }, /* 94.5000, - 7,55, 4 */
+    { 0x00005303, (97L << 16)  | ((5200L * 65536L) / 10000L) }, /* 97.5200, - 6,49, 4 */
+    { 0x00002183, (100L << 16) | ((1870L * 65536L) / 10000L) }, /* 100.187, - 3,25, 4 */
+    { 0x00002122, (101L << 16) | ((4200L * 65536L) / 10000L) }, /* 101.420, - 3,19, 3 */
+    { 0x00001081, (108L << 16) | ((0000L * 65536L) / 10000L) }, /* 108.00,  - 2, 9, 2 */
+    { 0x00006201, (113L << 16) | ((3100L * 65536L) / 10000L) }, /* 113.31,  - 7,33, 2 */
+    { 0x00000041, (119L << 16) | ((6500L * 65536L) / 10000L) }, /* 119.65,  - 1, 5, 2 */
+    { 0x000041A1, (129L << 16) | ((6000L * 65536L) / 10000L) }, /* 129.60,  - 5,27, 2 */
+    { 0x00002182, (133L << 16) | ((5000L * 65536L) / 10000L) }, /* 133.50,  - 3,25, 3 */
+    { 0x000041B1, (135L << 16) | ((0000L * 65536L) / 10000L) }, /* 135.00,  - 5,28, 2 */
+    { 0x00000051, (144L << 16) | ((0000L * 65536L) / 10000L) }, /* 144.00,  - 1, 6, 2 */
+    { 0x000041E1, (148L << 16) | ((5000L * 65536L) / 10000L) }, /* 148.50,  - 5,31, 2 */
+    { 0x000062D1, (157L << 16) | ((5000L * 65536L) / 10000L) }, /* 157.50,  - 7,46, 2 */
+    { 0x000031A1, (162L << 16) | ((0000L * 65536L) / 10000L) }, /* 162.00,  - 4,27, 2 */
+    { 0x00000061, (169L << 16) | ((2030L * 65536L) / 10000L) }, /* 169.203, - 1, 7, 2 */
+    { 0x00004231, (172L << 16) | ((8000L * 65536L) / 10000L) }, /* 172.800, - 5,36, 2 */
+    { 0x00002151, (175L << 16) | ((5000L * 65536L) / 10000L) }, /* 175.50,  - 3,22, 2 */
+    { 0x000052E1, (189L << 16) | ((0000L * 65536L) / 10000L) }, /* 189.00,  - 6,47, 2 */
+    { 0x00000071, (192L << 16) | ((0000L * 65536L) / 10000L) }, /* 192.00,  - 1, 8, 2 */
+    { 0x00003201, (198L << 16) | ((0000L * 65536L) / 10000L) }, /* 198.00,  - 4,33, 2 */
+    { 0x00004291, (202L << 16) | ((5000L * 65536L) / 10000L) }, /* 202.50,  - 5,42, 2 */
+    { 0x00001101, (204L << 16) | ((7500L * 65536L) / 10000L) }, /* 204.75,  - 2,17, 2 */
+    { 0x00007481, (218L << 16) | ((2500L * 65536L) / 10000L) }, /* 218.25,  - 8,73, 2 */
+    { 0x00004170, (229L << 16) | ((5000L * 65536L) / 10000L) }, /* 229.50,  - 5,24, 1 */
+    { 0x00006210, (234L << 16) | ((0000L * 65536L) / 10000L) }, /* 234.00,  - 7,34, 1 */
+    { 0x00003140, (251L << 16) | ((1820L * 65536L) / 10000L) }, /* 251.182, - 4,21, 1 */
+    { 0x00006250, (261L << 16) | ((0000L * 65536L) / 10000L) }, /* 261.00,  - 7,38, 1 */
+    { 0x000041C0, (278L << 16) | ((4000L * 65536L) / 10000L) }, /* 278.40,  - 5,29, 1 */
+    { 0x00005220, (280L << 16) | ((6400L * 65536L) / 10000L) }, /* 280.64,  - 6,35, 1 */
+    { 0x00000050, (288L << 16) | ((0000L * 65536L) / 10000L) }, /* 288.00,  - 1, 6, 1 */
+    { 0x000041E0, (297L << 16) | ((0000L * 65536L) / 10000L) }, /* 297.00,  - 5,31, 1 */
+    { 0x00002130, (320L << 16) | ((2070L * 65536L) / 10000L) }, /* 320.207, - 3,20, 1 */
+    { 0x00006310, (341L << 16) | ((3490L * 65536L) / 10000L) }  /* 341.349, - 7,50, 1 */
+};
+
+#define NUM_CIMARRON_PLL_FREQUENCIES sizeof(CimarronPLLFrequencies) / sizeof(PLL_FREQUENCY)
+
+/*-----------------------------------*/
+/*  PREDEFINED FILTER COEFFICIENTS   */
+/*-----------------------------------*/
+
+unsigned long CimarronHorizontalGraphicsFilter[][2] =
+{
+	{0x1284A7D5, 0x000017D5 }, /*  -43,  297,  296,  -43,    5  */
+    {0x12A497D7, 0x000013D6 }, /*  -41,  293,  298,  -42,    4  */
+    {0x12D48BD7, 0x000013D6 }, /*  -41,  290,  301,  -42,    4  */
+    {0x13147FD7, 0x000013D5 }, /*  -41,  287,  305,  -43,    4  */
+    {0x133473D8, 0x000013D5 }, /*  -40,  284,  307,  -43,    4  */
+    {0x136467D8, 0x000013D5 }, /*  -40,  281,  310,  -43,    4  */
+    {0x13945FD8, 0x000013D4 }, /*  -40,  279,  313,  -44,    4  */
+    {0x13B453D9, 0x000013D4 }, /*  -39,  276,  315,  -44,    4  */
+    {0x13E447D9, 0x000013D4 }, /*  -39,  273,  318,  -44,    4  */
+    {0x14143BDA, 0x000013D3 }, /*  -38,  270,  321,  -45,    4  */
+    {0x143433DA, 0x000013D3 }, /*  -38,  268,  323,  -45,    4  */
+    {0x146427DA, 0x000013D3 }, /*  -38,  265,  326,  -45,    4  */
+    {0x14941BDB, 0x000013D2 }, /*  -37,  262,  329,  -46,    4  */
+    {0x14C40FDB, 0x000013D2 }, /*  -37,  259,  332,  -46,    4  */
+    {0x14F407DA, 0x000017D1 }, /*  -38,  257,  335,  -47,    5  */
+    {0x1503FBDC, 0x000013D2 }, /*  -36,  254,  336,  -46,    4  */
+    {0x1543F3DB, 0x000017D0 }, /*  -37,  252,  340,  -48,    5  */
+    {0x1563E3DD, 0x000013D1 }, /*  -35,  248,  342,  -47,    4  */
+    {0x1593D7DD, 0x000013D1 }, /*  -35,  245,  345,  -47,    4  */
+    {0x15B3CFDD, 0x000013D1 }, /*  -35,  243,  347,  -47,    4  */
+    {0x15E3C3DE, 0x000013D0 }, /*  -34,  240,  350,  -48,    4  */
+    {0x1613B7DE, 0x000013D0 }, /*  -34,  237,  353,  -48,    4  */
+    {0x1633ABDF, 0x000013D0 }, /*  -33,  234,  355,  -48,    4  */
+    {0x16639FDF, 0x000013D0 }, /*  -33,  231,  358,  -48,    4  */
+    {0x167397E0, 0x000013D0 }, /*  -32,  229,  359,  -48,    4  */
+    {0x16B38BE0, 0x000013CF }, /*  -32,  226,  363,  -49,    4  */
+    {0x16E383DF, 0x000017CE }, /*  -33,  224,  366,  -50,    5  */
+    {0x170373E1, 0x000013CF }, /*  -31,  220,  368,  -49,    4  */
+    {0x17236BE1, 0x000013CF }, /*  -31,  218,  370,  -49,    4  */
+    {0x17435FE2, 0x000013CF }, /*  -30,  215,  372,  -49,    4  */
+    {0x177353E2, 0x000013CF }, /*  -30,  212,  375,  -49,    4  */
+    {0x17B34BE1, 0x000017CD }, /*  -31,  210,  379,  -51,    5  */
+    {0x17C33FE3, 0x000013CE }, /*  -29,  207,  380,  -50,    4  */
+    {0x17F333E3, 0x000013CE }, /*  -29,  204,  383,  -50,    4  */
+    {0x181327E4, 0x000013CE }, /*  -28,  201,  385,  -50,    4  */
+    {0x18431FE3, 0x000017CD }, /*  -29,  199,  388,  -51,    5  */
+    {0x186313E4, 0x000013CE }, /*  -28,  196,  390,  -50,    4  */
+    {0x188307E5, 0x000013CE }, /*  -27,  193,  392,  -50,    4  */
+    {0x18B2FBE5, 0x000013CE }, /*  -27,  190,  395,  -50,    4  */
+    {0x18C2F3E6, 0x000013CE }, /*  -26,  188,  396,  -50,    4  */
+    {0x18F2E7E6, 0x000013CE }, /*  -26,  185,  399,  -50,    4  */
+    {0x1912DBE7, 0x000013CE }, /*  -25,  182,  401,  -50,    4  */
+    {0x1952D3E6, 0x000017CC }, /*  -26,  180,  405,  -52,    5  */
+    {0x1972CBE6, 0x000017CC }, /*  -26,  178,  407,  -52,    5  */
+    {0x1992BFE7, 0x000017CC }, /*  -25,  175,  409,  -52,    5  */
+    {0x19C2B3E7, 0x000017CC }, /*  -25,  172,  412,  -52,    5  */
+    {0x19D2A7E9, 0x000013CD }, /*  -23,  169,  413,  -51,    4  */
+    {0x1A029FE8, 0x000017CC }, /*  -24,  167,  416,  -52,    5  */
+    {0x1A1293E9, 0x000013CE }, /*  -23,  164,  417,  -50,    4  */
+    {0x1A3287EA, 0x000013CE }, /*  -22,  161,  419,  -50,    4  */
+    {0x1A627FE9, 0x000017CD }, /*  -23,  159,  422,  -51,    5  */
+    {0x1A7273EB, 0x000013CE }, /*  -21,  156,  423,  -50,    4  */
+    {0x1AA267EB, 0x000013CE }, /*  -21,  153,  426,  -50,    4  */
+    {0x1AC25FEB, 0x000013CE }, /*  -21,  151,  428,  -50,    4  */
+    {0x1AE253EC, 0x000013CE }, /*  -20,  148,  430,  -50,    4  */
+    {0x1B124BEB, 0x000017CD }, /*  -21,  146,  433,  -51,    5  */
+    {0x1B223FED, 0x000013CE }, /*  -19,  143,  434,  -50,    4  */
+    {0x1B5237EC, 0x000017CD }, /*  -20,  141,  437,  -51,    5  */
+    {0x1B622BED, 0x000013CF }, /*  -19,  138,  438,  -49,    4  */
+    {0x1B821FEE, 0x000013CF }, /*  -18,  135,  440,  -49,    4  */
+    {0x1BA217EE, 0x000013CF }, /*  -18,  133,  442,  -49,    4  */
+    {0x1BC20BEF, 0x000013CF }, /*  -17,  130,  444,  -49,    4  */
+    {0x1BE203EF, 0x000013CF }, /*  -17,  128,  446,  -49,    4  */
+    {0x1C01FBEE, 0x000017CF }, /*  -18,  126,  448,  -49,    5  */
+    {0x1C11EFF0, 0x000013D0 }, /*  -16,  123,  449,  -48,    4  */
+    {0x1C41E7EF, 0x000017CF }, /*  -17,  121,  452,  -49,    5  */
+    {0x1C61DFEF, 0x000017CF }, /*  -17,  119,  454,  -49,    5  */
+    {0x1C61D3F1, 0x000013D1 }, /*  -15,  116,  454,  -47,    4  */
+    {0x1C91CBF0, 0x000017D0 }, /*  -16,  114,  457,  -48,    5  */
+    {0x1CA1BFF2, 0x000013D1 }, /*  -14,  111,  458,  -47,    4  */
+    {0x1CC1B3F2, 0x000013D2 }, /*  -14,  108,  460,  -46,    4  */
+    {0x1CE1AFF1, 0x000017D1 }, /*  -15,  107,  462,  -47,    5  */
+    {0x1CF1A3F3, 0x000013D2 }, /*  -13,  104,  463,  -46,    4  */
+    {0x1D1197F3, 0x000013D3 }, /*  -13,  101,  465,  -45,    4  */
+    {0x1D3197F2, 0x000013D2 }, /*  -14,  101,  467,  -46,    4  */
+    {0x1D518BF3, 0x000013D2 }, /*  -13,   98,  469,  -46,    4  */
+    {0x1D6183F3, 0x000013D3 }, /*  -13,   96,  470,  -45,    4  */
+    {0x1D817BF3, 0x000013D3 }, /*  -13,   94,  472,  -45,    4  */
+    {0x1D916FF4, 0x000013D4 }, /*  -12,   91,  473,  -44,    4  */
+    {0x1DB167F4, 0x000013D4 }, /*  -12,   89,  475,  -44,    4  */
+    {0x1DC15FF4, 0x000013D5 }, /*  -12,   87,  476,  -43,    4  */
+    {0x1DE153F5, 0x000013D5 }, /*  -11,   84,  478,  -43,    4  */
+    {0x1DF14BF5, 0x000013D6 }, /*  -11,   82,  479,  -42,    4  */
+    {0x1E1143F5, 0x000013D6 }, /*  -11,   80,  481,  -42,    4  */
+    {0x1E1137F7, 0x00000FD8 }, /*   -9,   77,  481,  -40,    3  */
+    {0x1E3133F6, 0x000013D7 }, /*  -10,   76,  483,  -41,    4  */
+    {0x1E412BF6, 0x000013D8 }, /*  -10,   74,  484,  -40,    4  */
+    {0x1E611FF7, 0x000013D8 }, /*   -9,   71,  486,  -40,    4  */
+    {0x1E7117F7, 0x000013D9 }, /*   -9,   69,  487,  -39,    4  */
+    {0x1E810FF7, 0x000013DA }, /*   -9,   67,  488,  -38,    4  */
+    {0x1E9107F8, 0x000013DA }, /*   -8,   65,  489,  -38,    4  */
+    {0x1EA0FFF8, 0x000013DB }, /*   -8,   63,  490,  -37,    4  */
+    {0x1EB0F3F9, 0x00000FDD }, /*   -7,   60,  491,  -35,    3  */
+    {0x1ED0EFF8, 0x000013DC }, /*   -8,   59,  493,  -36,    4  */
+    {0x1EE0E7F9, 0x00000FDD }, /*   -7,   57,  494,  -35,    3  */
+    {0x1EF0DFF9, 0x00000FDE }, /*   -7,   55,  495,  -34,    3  */
+    {0x1F00D7F9, 0x00000FDF }, /*   -7,   53,  496,  -33,    3  */
+    {0x1F10CFFA, 0x00000FDF }, /*   -6,   51,  497,  -33,    3  */
+    {0x1F20C7FA, 0x00000FE0 }, /*   -6,   49,  498,  -32,    3  */
+    {0x1F20C3FA, 0x00000FE1 }, /*   -6,   48,  498,  -31,    3  */
+    {0x1F30BBFA, 0x00000FE2 }, /*   -6,   46,  499,  -30,    3  */
+    {0x1F40AFFB, 0x00000FE3 }, /*   -5,   43,  500,  -29,    3  */
+    {0x1F50A7FB, 0x00000FE4 }, /*   -5,   41,  501,  -28,    3  */
+    {0x1F60A3FB, 0x00000FE4 }, /*   -5,   40,  502,  -28,    3  */
+    {0x1F709BFB, 0x00000FE5 }, /*   -5,   38,  503,  -27,    3  */
+    {0x1F7093FC, 0x00000FE6 }, /*   -4,   36,  503,  -26,    3  */
+    {0x1F808FFC, 0x00000BE7 }, /*   -4,   35,  504,  -25,    2  */
+    {0x1F9087FC, 0x00000BE8 }, /*   -4,   33,  505,  -24,    2  */
+    {0x1F9083FC, 0x00000BE9 }, /*   -4,   32,  505,  -23,    2  */
+    {0x1FA077FD, 0x00000BEA }, /*   -3,   29,  506,  -22,    2  */
+    {0x1FA073FD, 0x00000BEB }, /*   -3,   28,  506,  -21,    2  */
+    {0x1FB06BFD, 0x00000BEC }, /*   -3,   26,  507,  -20,    2  */
+    {0x1FC063FD, 0x00000BED }, /*   -3,   24,  508,  -19,    2  */
+    {0x1FC05BFE, 0x00000BEE }, /*   -2,   22,  508,  -18,    2  */
+    {0x1FC057FE, 0x00000BEF }, /*   -2,   21,  508,  -17,    2  */
+    {0x1FD053FE, 0x000007F0 }, /*   -2,   20,  509,  -16,    1  */
+    {0x1FD04BFE, 0x000007F2 }, /*   -2,   18,  509,  -14,    1  */
+    {0x1FE043FE, 0x000007F3 }, /*   -2,   16,  510,  -13,    1  */
+    {0x1FE03BFF, 0x000007F4 }, /*   -1,   14,  510,  -12,    1  */
+    {0x1FE037FF, 0x000007F5 }, /*   -1,   13,  510,  -11,    1  */
+    {0x1FE033FF, 0x000007F6 }, /*   -1,   12,  510,  -10,    1  */
+    {0x1FF02BFF, 0x000007F7 }, /*   -1,   10,  511,   -9,    1  */
+    {0x1FF027FF, 0x000003F9 }, /*   -1,    9,  511,   -7,    0  */
+    {0x1FF01C00, 0x000003FA }, /*    0,    7,  511,   -6,    0  */
+    {0x1FF01800, 0x000003FB }, /*    0,    6,  511,   -5,    0  */
+    {0x1FF01400, 0x000003FC }, /*    0,    5,  511,   -4,    0  */
+    {0x1FF00C00, 0x000003FE }, /*    0,    3,  511,   -2,    0  */
+    {0x1FF00800, 0x000003FF }, /*    0,    2,  511,   -1,    0  */
+    {0x1FF00400, 0x00000000 }, /*    0,    1,  511,    0,    0  */
+    {0x1FFFFC00, 0x00000002 }, /*    0,   -1,  511,    2,    0  */
+    {0x1FFFF800, 0x00000003 }, /*    0,   -2,  511,    3,    0  */
+    {0x1FFFF000, 0x00000005 }, /*    0,   -4,  511,    5,    0  */
+    {0x1FFFEC00, 0x00000006 }, /*    0,   -5,  511,    6,    0  */
+    {0x1FFFE800, 0x00000007 }, /*    0,   -6,  511,    7,    0  */
+    {0x1FFFE400, 0x000FFC09 }, /*    0,   -7,  511,    9,   -1  */
+    {0x1FFFDC01, 0x000FFC0A }, /*    1,   -9,  511,   10,   -1  */
+    {0x1FEFDC01, 0x000FFC0B }, /*    1,   -9,  510,   11,   -1  */
+    {0x1FEFD401, 0x000FFC0D }, /*    1,  -11,  510,   13,   -1  */
+    {0x1FEFD001, 0x000FFC0E }, /*    1,  -12,  510,   14,   -1  */
+    {0x1FEFCC01, 0x000FF810 }, /*    1,  -13,  510,   16,   -2  */
+    {0x1FDFCC01, 0x000FF811 }, /*    1,  -13,  509,   17,   -2  */
+    {0x1FDFC401, 0x000FF813 }, /*    1,  -15,  509,   19,   -2  */
+    {0x1FCFC002, 0x000FF814 }, /*    2,  -16,  508,   20,   -2  */
+    {0x1FCFB802, 0x000FF816 }, /*    2,  -18,  508,   22,   -2  */
+    {0x1FCFB402, 0x000FF418 }, /*    2,  -19,  508,   24,   -3  */
+    {0x1FBFB402, 0x000FF419 }, /*    2,  -19,  507,   25,   -3  */
+    {0x1FAFB002, 0x000FF41B }, /*    2,  -20,  506,   27,   -3  */
+    {0x1FAFA802, 0x000FF41D }, /*    2,  -22,  506,   29,   -3  */
+    {0x1F9FA802, 0x000FF01F }, /*    2,  -22,  505,   31,   -4  */
+    {0x1F9FA402, 0x000FF020 }, /*    2,  -23,  505,   32,   -4  */
+    {0x1F8FA002, 0x000FF022 }, /*    2,  -24,  504,   34,   -4  */
+    {0x1F7F9803, 0x000FF024 }, /*    3,  -26,  503,   36,   -4  */
+    {0x1F7F9403, 0x000FEC26 }, /*    3,  -27,  503,   38,   -5  */
+    {0x1F6F9003, 0x000FEC28 }, /*    3,  -28,  502,   40,   -5  */
+    {0x1F5F9003, 0x000FEC29 }, /*    3,  -28,  501,   41,   -5  */
+    {0x1F4F8C03, 0x000FEC2B }, /*    3,  -29,  500,   43,   -5  */
+    {0x1F3F8C03, 0x000FE82D }, /*    3,  -29,  499,   45,   -6  */
+    {0x1F2F8803, 0x000FE82F }, /*    3,  -30,  498,   47,   -6  */
+    {0x1F2F8003, 0x000FE831 }, /*    3,  -32,  498,   49,   -6  */
+    {0x1F1F7C03, 0x000FE833 }, /*    3,  -33,  497,   51,   -6  */
+    {0x1F0F7C03, 0x000FE435 }, /*    3,  -33,  496,   53,   -7  */
+    {0x1EFF7803, 0x000FE437 }, /*    3,  -34,  495,   55,   -7  */
+    {0x1EEF7403, 0x000FE439 }, /*    3,  -35,  494,   57,   -7  */
+    {0x1EDF7004, 0x000FE03B }, /*    4,  -36,  493,   59,   -8  */
+    {0x1EBF7403, 0x000FE43C }, /*    3,  -35,  491,   60,   -7  */
+    {0x1EAF6C04, 0x000FE03F }, /*    4,  -37,  490,   63,   -8  */
+    {0x1E9F6804, 0x000FE041 }, /*    4,  -38,  489,   65,   -8  */
+    {0x1E8F6804, 0x000FDC43 }, /*    4,  -38,  488,   67,   -9  */
+    {0x1E7F6404, 0x000FDC45 }, /*    4,  -39,  487,   69,   -9  */
+    {0x1E6F6004, 0x000FDC47 }, /*    4,  -40,  486,   71,   -9  */
+    {0x1E4F6404, 0x000FD849 }, /*    4,  -39,  484,   73,  -10  */
+    {0x1E3F6004, 0x000FD84B }, /*    4,  -40,  483,   75,  -10  */
+    {0x1E1F6003, 0x000FDC4D }, /*    3,  -40,  481,   77,   -9  */
+    {0x1E1F5804, 0x000FD450 }, /*    4,  -42,  481,   80,  -11  */
+    {0x1DFF5804, 0x000FD452 }, /*    4,  -42,  479,   82,  -11  */
+    {0x1DEF5404, 0x000FD454 }, /*    4,  -43,  478,   84,  -11  */
+    {0x1DCF5804, 0x000FD056 }, /*    4,  -42,  476,   86,  -12  */
+    {0x1DBF5004, 0x000FD059 }, /*    4,  -44,  475,   89,  -12  */
+    {0x1D9F5004, 0x000FD05B }, /*    4,  -44,  473,   91,  -12  */
+    {0x1D8F5004, 0x000FCC5D }, /*    4,  -44,  472,   93,  -13  */
+    {0x1D6F5004, 0x000FCC5F }, /*    4,  -44,  470,   95,  -13  */
+    {0x1D5F4804, 0x000FCC62 }, /*    4,  -46,  469,   98,  -13  */
+    {0x1D3F4C04, 0x000FC864 }, /*    4,  -45,  467,  100,  -14  */
+    {0x1D1F4C04, 0x000FCC65 }, /*    4,  -45,  465,  101,  -13  */
+    {0x1CFF4804, 0x000FCC68 }, /*    4,  -46,  463,  104,  -13  */
+    {0x1CEF4405, 0x000FC46B }, /*    5,  -47,  462,  107,  -15  */
+    {0x1CCF4804, 0x000FC86C }, /*    4,  -46,  460,  108,  -14  */
+    {0x1CAF4404, 0x000FC86F }, /*    4,  -47,  458,  111,  -14  */
+    {0x1C9F4005, 0x000FC072 }, /*    5,  -48,  457,  114,  -16  */
+    {0x1C6F4404, 0x000FC474 }, /*    4,  -47,  454,  116,  -15  */
+    {0x1C6F3C05, 0x000FBC77 }, /*    5,  -49,  454,  119,  -17  */
+    {0x1C4F3C05, 0x000FBC79 }, /*    5,  -49,  452,  121,  -17  */
+    {0x1C1F4004, 0x000FC07B }, /*    4,  -48,  449,  123,  -16  */
+    {0x1C0F3C05, 0x000FB87E }, /*    5,  -49,  448,  126,  -18  */
+    {0x1BEF3C04, 0x000FBC80 }, /*    4,  -49,  446,  128,  -17  */
+    {0x1BCF3C04, 0x000FBC82 }, /*    4,  -49,  444,  130,  -17  */
+    {0x1BAF3C04, 0x000FB885 }, /*    4,  -49,  442,  133,  -18  */
+    {0x1B8F3C04, 0x000FB887 }, /*    4,  -49,  440,  135,  -18  */
+    {0x1B6F3C04, 0x000FB48A }, /*    4,  -49,  438,  138,  -19  */
+    {0x1B5F3405, 0x000FB08D }, /*    5,  -51,  437,  141,  -20  */
+    {0x1B2F3804, 0x000FB48F }, /*    4,  -50,  434,  143,  -19  */
+    {0x1B1F3405, 0x000FAC92 }, /*    5,  -51,  433,  146,  -21  */
+    {0x1AEF3804, 0x000FB094 }, /*    4,  -50,  430,  148,  -20  */
+    {0x1ACF3804, 0x000FAC97 }, /*    4,  -50,  428,  151,  -21  */
+    {0x1AAF3804, 0x000FAC99 }, /*    4,  -50,  426,  153,  -21  */
+    {0x1A7F3804, 0x000FAC9C }, /*    4,  -50,  423,  156,  -21  */
+    {0x1A6F3405, 0x000FA49F }, /*    5,  -51,  422,  159,  -23  */
+    {0x1A3F3804, 0x000FA8A1 }, /*    4,  -50,  419,  161,  -22  */
+    {0x1A1F3804, 0x000FA4A4 }, /*    4,  -50,  417,  164,  -23  */
+    {0x1A0F3005, 0x000FA0A7 }, /*    5,  -52,  416,  167,  -24  */
+    {0x19DF3404, 0x000FA4A9 }, /*    4,  -51,  413,  169,  -23  */
+    {0x19CF3005, 0x000F9CAC }, /*    5,  -52,  412,  172,  -25  */
+    {0x199F3005, 0x000F9CAF }, /*    5,  -52,  409,  175,  -25  */
+    {0x197F3005, 0x000F98B2 }, /*    5,  -52,  407,  178,  -26  */
+    {0x195F3005, 0x000F98B4 }, /*    5,  -52,  405,  180,  -26  */
+    {0x191F3804, 0x000F9CB6 }, /*    4,  -50,  401,  182,  -25  */
+    {0x18FF3804, 0x000F98B9 }, /*    4,  -50,  399,  185,  -26  */
+    {0x18CF3804, 0x000F98BC }, /*    4,  -50,  396,  188,  -26  */
+    {0x18BF3804, 0x000F94BE }, /*    4,  -50,  395,  190,  -27  */
+    {0x188F3804, 0x000F94C1 }, /*    4,  -50,  392,  193,  -27  */
+    {0x186F3804, 0x000F90C4 }, /*    4,  -50,  390,  196,  -28  */
+    {0x184F3405, 0x000F8CC7 }, /*    5,  -51,  388,  199,  -29  */
+    {0x181F3804, 0x000F90C9 }, /*    4,  -50,  385,  201,  -28  */
+    {0x17FF3804, 0x000F8CCC }, /*    4,  -50,  383,  204,  -29  */
+    {0x17CF3804, 0x000F8CCF }, /*    4,  -50,  380,  207,  -29  */
+    {0x17BF3405, 0x000F84D2 }, /*    5,  -51,  379,  210,  -31  */
+    {0x177F3C04, 0x000F88D4 }, /*    4,  -49,  375,  212,  -30  */
+    {0x174F3C04, 0x000F88D7 }, /*    4,  -49,  372,  215,  -30  */
+    {0x172F3C04, 0x000F84DA }, /*    4,  -49,  370,  218,  -31  */
+    {0x170F3C04, 0x000F84DC }, /*    4,  -49,  368,  220,  -31  */
+    {0x16EF3805, 0x000F7CE0 }, /*    5,  -50,  366,  224,  -33  */
+    {0x16BF3C04, 0x000F80E2 }, /*    4,  -49,  363,  226,  -32  */
+    {0x167F4004, 0x000F80E5 }, /*    4,  -48,  359,  229,  -32  */
+    {0x166F4004, 0x000F7CE7 }, /*    4,  -48,  358,  231,  -33  */
+    {0x163F4004, 0x000F7CEA }, /*    4,  -48,  355,  234,  -33  */
+    {0x161F4004, 0x000F78ED }, /*    4,  -48,  353,  237,  -34  */
+    {0x15EF4004, 0x000F78F0 }, /*    4,  -48,  350,  240,  -34  */
+    {0x15BF4404, 0x000F74F3 }, /*    4,  -47,  347,  243,  -35  */
+    {0x159F4404, 0x000F74F5 }, /*    4,  -47,  345,  245,  -35  */
+    {0x156F4404, 0x000F74F8 }, /*    4,  -47,  342,  248,  -35  */
+    {0x154F4005, 0x000F6CFC }, /*    5,  -48,  340,  252,  -37  */
+    {0x150F4804, 0x000F70FE }, /*    4,  -46,  336,  254,  -36  */
+    {0x14FF4405, 0x000F6901 }, /*    5,  -47,  335,  257,  -38  */
+    {0x14CF4804, 0x000F6D03 }, /*    4,  -46,  332,  259,  -37  */
+    {0x149F4804, 0x000F6D06 }, /*    4,  -46,  329,  262,  -37  */
+    {0x146F4C04, 0x000F6909 }, /*    4,  -45,  326,  265,  -38  */
+    {0x143F4C04, 0x000F690C }, /*    4,  -45,  323,  268,  -38  */
+    {0x141F4C04, 0x000F690E }, /*    4,  -45,  321,  270,  -38  */
+    {0x13EF5004, 0x000F6511 }, /*    4,  -44,  318,  273,  -39  */
+    {0x13BF5004, 0x000F6514 }, /*    4,  -44,  315,  276,  -39  */
+    {0x139F5004, 0x000F6117 }, /*    4,  -44,  313,  279,  -40  */
+    {0x136F5404, 0x000F6119 }, /*    4,  -43,  310,  281,  -40  */
+    {0x133F5404, 0x000F611C }, /*    4,  -43,  307,  284,  -40  */
+    {0x131F5404, 0x000F5D1F }, /*    4,  -43,  305,  287,  -41  */
+    {0x12DF5C04, 0x000F5D21 }, /*    4,  -41,  301,  289,  -41  */
+    {0x12AF5C04, 0x000F5D24 }, /*    4,  -41,  298,  292,  -41  */
+};
+
+unsigned long CimarronVerticalGraphicsFilter[] =
+{
+	0x3F840D05, /* 261, 259,  -8  */
+    0x3F841D01, /* 257, 263,  -8  */
+    0x3F8428FE, /* 254, 266,  -8  */
+    0x3F8438FA, /* 250, 270,  -8  */
+    0x3F8444F7, /* 247, 273,  -8  */
+    0x3F8450F4, /* 244, 276,  -8  */
+    0x3F845CF1, /* 241, 279,  -8  */
+    0x3F8468EE, /* 238, 282,  -8  */
+    0x3F8474EB, /* 235, 285,  -8  */
+    0x3F8480E8, /* 232, 288,  -8  */
+    0x3F7490E5, /* 229, 292,  -9  */
+    0x3F749CE2, /* 226, 295,  -9  */
+    0x3F74ACDE, /* 222, 299,  -9  */
+    0x3F74B8DB, /* 219, 302,  -9  */
+    0x3F74C0D9, /* 217, 304,  -9  */
+    0x3F74CCD6, /* 214, 307,  -9  */
+    0x3F74D8D3, /* 211, 310,  -9  */
+    0x3F74E8CF, /* 207, 314,  -9  */
+    0x3F74F4CC, /* 204, 317,  -9  */
+    0x3F7500C9, /* 201, 320,  -9  */
+    0x3F750CC6, /* 198, 323,  -9  */
+    0x3F7518C3, /* 195, 326,  -9  */
+    0x3F7520C1, /* 193, 328,  -9  */
+    0x3F7530BD, /* 189, 332,  -9  */
+    0x3F753CBA, /* 186, 335,  -9  */
+    0x3F7548B7, /* 183, 338,  -9  */
+    0x3F6558B4, /* 180, 342, -10  */
+    0x3F6560B2, /* 178, 344, -10  */
+    0x3F656CAF, /* 175, 347, -10  */
+    0x3F6578AC, /* 172, 350, -10  */
+    0x3F6584A9, /* 169, 353, -10  */
+    0x3F658CA7, /* 167, 355, -10  */
+    0x3F6598A4, /* 164, 358, -10  */
+    0x3F65A8A0, /* 160, 362, -10  */
+    0x3F65B09E, /* 158, 364, -10  */
+    0x3F65BC9B, /* 155, 367, -10  */
+    0x3F65C499, /* 153, 369, -10  */
+    0x3F65D096, /* 150, 372, -10  */
+    0x3F55E093, /* 147, 376, -11  */
+    0x3F55E891, /* 145, 378, -11  */
+    0x3F55F48E, /* 142, 381, -11  */
+    0x3F56008B, /* 139, 384, -11  */
+    0x3F560C88, /* 136, 387, -11  */
+    0x3F561486, /* 134, 389, -11  */
+    0x3F562083, /* 131, 392, -11  */
+    0x3F562881, /* 129, 394, -11  */
+    0x3F56347E, /* 126, 397, -11  */
+    0x3F56407B, /* 123, 400, -11  */
+    0x3F564879, /* 121, 402, -11  */
+    0x3F465876, /* 118, 406, -12  */
+    0x3F466074, /* 116, 408, -12  */
+    0x3F466872, /* 114, 410, -12  */
+    0x3F46746F, /* 111, 413, -12  */
+    0x3F467C6D, /* 109, 415, -12  */
+    0x3F46846B, /* 107, 417, -12  */
+    0x3F468C69, /* 105, 419, -12  */
+    0x3F469866, /* 102, 422, -12  */
+    0x3F46A064, /* 100, 424, -12  */
+    0x3F46AC61, /*  97, 427, -12  */
+    0x3F46B45F, /*  95, 429, -12  */
+    0x3F46BC5D, /*  93, 431, -12  */
+    0x3F46C45B, /*  91, 433, -12  */
+    0x3F46CC59, /*  89, 435, -12  */
+    0x3F36DC56, /*  86, 439, -13  */
+    0x3F36E454, /*  84, 441, -13  */
+    0x3F36EC52, /*  82, 443, -13  */
+    0x3F36F450, /*  80, 445, -13  */
+    0x3F36FC4E, /*  78, 447, -13  */
+    0x3F37004D, /*  77, 448, -13  */
+    0x3F370C4A, /*  74, 451, -13  */
+    0x3F371448, /*  72, 453, -13  */
+    0x3F371C46, /*  70, 455, -13  */
+    0x3F372444, /*  68, 457, -13  */
+    0x3F372C42, /*  66, 459, -13  */
+    0x3F373440, /*  64, 461, -13  */
+    0x3F37383F, /*  63, 462, -13  */
+    0x3F37403D, /*  61, 464, -13  */
+    0x3F37483B, /*  59, 466, -13  */
+    0x3F375039, /*  57, 468, -13  */
+    0x3F375438, /*  56, 469, -13  */
+    0x3F375C36, /*  54, 471, -13  */
+    0x3F376434, /*  52, 473, -13  */
+    0x3F376833, /*  51, 474, -13  */
+    0x3F377031, /*  49, 476, -13  */
+    0x3F377430, /*  48, 477, -13  */
+    0x3F377C2E, /*  46, 479, -13  */
+    0x3F37842C, /*  44, 481, -13  */
+    0x3F37882B, /*  43, 482, -13  */
+    0x3F47882A, /*  42, 482, 
