diff -Nru kernel-2.6.18geode-hurricane.orig/Documentation/fb/geodefb.txt kernel-2.6.18geode-hurricane/Documentation/fb/geodefb.txt
--- kernel-2.6.18geode-hurricane.orig/Documentation/fb/geodefb.txt 1970-01-01 01:00:00.000000000 +0100
+++ kernel-2.6.18geode-hurricane/Documentation/fb/geodefb.txt 2006-12-01 13:21:21.000000000 +0100
@@ -0,0 +1,95 @@
+geodefb.txt
+
+This is the documentation for the AMD Geode LX framebuffer driver.
+
+Kernel Build Configuration Parameters
+-------------------------------------
+These kernel build parameters are operated using "make xconfig" or
+"make menuconfig" from the kernel source root directory.
+The parameter path to these parameters is:
+Device Drivers
+ Graphics Support
+ Support for frame buffer devices
+ AMD Geode generic framebuffer support
+ AMD Geode LX framebuffer driver
+ AMD Geode LX console acceleration
+ AMD Geode Framebuffer panel support
+
+Config_Param Value Definition
+============ ===== ==========
+FB_GEODE (y/m/n) Build AMD Geode generic framebuffer support
+FB_GEODE_LX (y/n) Build AMD Geode LX framebuffer driver (selects CIMARRON)
+FB_GEODE_ACCEL (y/n) Build AMD Geode LX console acceleration
+FB_GEODE_PANEL (y/n) Build AMD Geode Framebuffer panel support
+
+
+Kernel Boot Command Line Argument Options
+-----------------------------------------
+If the geodefb driver has been built into the kernel (not as a module), then
+driver setup options are available via the kernel cmdline interface.
+
+kernel boot command line argument options are available using:
+video=geodefb:[, ...]
+option strings are one of three types:
+identifier as in video=geodefb:off
+identifier=value as in video=geodefb:vfreq=85
+noidenfier as in video=geodefb:noflatpanel
+
+video=option Definition
+============ ==========
+off - specify this option to disable the geodefb.
+vfreq= - specifies the default vertical refresh (default 60)
+vmode= - specifies a mode text string. (default = 640x480@60-16)
+no/compression - disables/enables compression display acceleration (default disabled)
+maxmem - Maximum amount of memory to use for the FB (default 12288K)
+no/accel - disables/enables rendering accelerations (default enabled)
+
+if the module was build with CONFIG_FB_GEODE_PANEL applied
+no/flatpanel - disable/enables flatpanel operation (default enabled)
+no/fphwscale - disable/enables flatpanel hardware scaling (default enabled)
+
+
+Module Parameters:
+------------------
+If geodefb was built as a module, then parameters can be applied
+when the modules is installed (via insmod/modprobe or modules.conf).
+When installing the module, new options are specified as follows:
+modprobe geodefb ... or
+insmod /path/geodefb.ko ...
+
+Module parameters:
+parameter Definition
+========= ==========
+vfreq - Set initial video refresh rate in cycles per second
+vmode - Set initial mode to x@refresh-bpp
+compression - Compression support (0=disabled or 1=enabled)
+maxmem - Maximum amount of memory to use for the FB (in Kbytes)
+accel - HW accleration support (0=disabled or 1=enabled)
+
+if the module was build with CONFIG_FB_GEODE_PANEL applied
+flatpanel - Flatpanel support (0=disabled or 1=enabled)
+fphwscale - FP Hardware Scaling (0=disabled or 1=enabled)
+
+
+Video Modes:
+------------
+The permissible mode parameter values are:
+geometry
+ 640x480, 800x600, 1024x768, 1152x864, 1280x1024, 1600x1200, 1920x1600
+refresh
+ 56, 60, 70, 72, 75, 85, 90, 100
+bpp
+ 8, 16, 32
+
+The permissible mode parameter combinations are defined by the cimarron
+driver, and in cimarron by cim_modes.c.
+
+
+Notes:
+-----
+Since building the geodefb normally select the cimarron driver, please
+review the procedures for building cimarron. To have the framebuffer
+driver work properly with X windows, it is normally necessary to create
+device nodes for /dev/cimarron and possibly links for /dev/videox.
+See cimarron module and lxv4l2 module documentation.
+
diff -Nru kernel-2.6.18geode-hurricane.orig/drivers/video/geode/geodefb1.h kernel-2.6.18geode-hurricane/drivers/video/geode/geodefb1.h
--- kernel-2.6.18geode-hurricane.orig/drivers/video/geode/geodefb1.h 1970-01-01 01:00:00.000000000 +0100
+++ kernel-2.6.18geode-hurricane/drivers/video/geode/geodefb1.h 2006-12-01 13:21:21.000000000 +0100
@@ -0,0 +1,65 @@
+/*
+ * 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
+ * */
+/*
+ * */
+/*
+ * Geode framebuffer header file
+ * */
+
+
+#ifndef GEODEFB_H_
+#define GEODEFB_H_
+
+#include
+
+#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);
+
+#endif
diff -Nru kernel-2.6.18geode-hurricane.orig/drivers/video/geode/geodefb_hw.c kernel-2.6.18geode-hurricane/drivers/video/geode/geodefb_hw.c
--- kernel-2.6.18geode-hurricane.orig/drivers/video/geode/geodefb_hw.c 1970-01-01 01:00:00.000000000 +0100
+++ kernel-2.6.18geode-hurricane/drivers/video/geode/geodefb_hw.c 2006-12-01 13:23:10.000000000 +0100
@@ -0,0 +1,105 @@
+/*
+ * 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
+ * */
+/*
+ * */
+/*
+ * Geode hardware specific routines
+ * */
+
+#include "geodefb1.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 -Nru kernel-2.6.18geode-hurricane.orig/drivers/video/geode/geodefb_lx_accel.c kernel-2.6.18geode-hurricane/drivers/video/geode/geodefb_lx_accel.c
--- kernel-2.6.18geode-hurricane.orig/drivers/video/geode/geodefb_lx_accel.c 1970-01-01 01:00:00.000000000 +0100
+++ kernel-2.6.18geode-hurricane/drivers/video/geode/geodefb_lx_accel.c 2006-12-01 13:22:47.000000000 +0100
@@ -0,0 +1,178 @@
+/*
+ * 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
+ * */
+/*
+ * */
+/*
+ * Geode LX acceleration routines
+ * */
+
+#include
+#include
+#include
+
+#include
+
+#include "geodefb1.h"
+#include "geodefb_lx.h"
+
+/* Matches ROP_ defines in fb.h */
+static unsigned char lx_rops[] = { 0xF0, 0x55 };
+
+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;
+}
+
+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 -Nru kernel-2.6.18geode-hurricane.orig/drivers/video/geode/geodefb_lx.c kernel-2.6.18geode-hurricane/drivers/video/geode/geodefb_lx.c
--- kernel-2.6.18geode-hurricane.orig/drivers/video/geode/geodefb_lx.c 1970-01-01 01:00:00.000000000 +0100
+++ kernel-2.6.18geode-hurricane/drivers/video/geode/geodefb_lx.c 2006-12-01 13:22:07.000000000 +0100
@@ -0,0 +1,802 @@
+/*
+ * 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
+ * */
+/*
+ * */
+/*
+ * Geode LX framebuffer driver
+ * */
+
+#include
+#include
+#include
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+/* For the console notifier */
+#include
+
+#include
+
+#include
+
+#include
+#include
+
+#include "geodefb1.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
+
+extern int soft_cursor (struct fb_info *info, struct fb_cursor *cursor);
+/* 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) {
+
+#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) {
+
+ 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 -Nru kernel-2.6.18geode-hurricane.orig/drivers/video/geode/geodefb_lx.h kernel-2.6.18geode-hurricane/drivers/video/geode/geodefb_lx.h
--- kernel-2.6.18geode-hurricane.orig/drivers/video/geode/geodefb_lx.h 1970-01-01 01:00:00.000000000 +0100
+++ kernel-2.6.18geode-hurricane/drivers/video/geode/geodefb_lx.h 2006-12-01 13:21:21.000000000 +0100
@@ -0,0 +1,60 @@
+/*
+ * 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
+ * */
+/*
+ * */
+/*
+ * Geode LX framebuffer header file
+ * */
+
+#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 -Nru kernel-2.6.18geode-hurricane.orig/drivers/video/geode/geodefb_modes.c kernel-2.6.18geode-hurricane/drivers/video/geode/geodefb_modes.c
--- kernel-2.6.18geode-hurricane.orig/drivers/video/geode/geodefb_modes.c 1970-01-01 01:00:00.000000000 +0100
+++ kernel-2.6.18geode-hurricane/drivers/video/geode/geodefb_modes.c 2006-12-01 13:21:21.000000000 +0100
@@ -0,0 +1,110 @@
+/*
+ * 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
+ * */
+/*
+ * */
+/*
+ * Geode framebuffer header file
+ * */
+
+#include
+#include "geodefb1.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 -Nru kernel-2.6.18geode-hurricane.orig/drivers/video/geode/Kconfig kernel-2.6.18geode-hurricane/drivers/video/geode/Kconfig
--- kernel-2.6.18geode-hurricane.orig/drivers/video/geode/Kconfig 2006-09-20 05:42:06.000000000 +0200
+++ kernel-2.6.18geode-hurricane/drivers/video/geode/Kconfig 2006-12-01 13:21:21.000000000 +0100
@@ -37,3 +37,26 @@
called gx1fb.
If unsure, say N.
+
+config FB_GEODE_LX
+ bool "AMD Geode LX framebuffer"
+ depends on FB && 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
diff -Nru kernel-2.6.18geode-hurricane.orig/drivers/video/geode/Makefile kernel-2.6.18geode-hurricane/drivers/video/geode/Makefile
--- kernel-2.6.18geode-hurricane.orig/drivers/video/geode/Makefile 2006-09-20 05:42:06.000000000 +0200
+++ kernel-2.6.18geode-hurricane/drivers/video/geode/Makefile 2006-12-01 13:22:27.000000000 +0100
@@ -1,7 +1,12 @@
# Makefile for the Geode family framebuffer drivers
+EXTRA_CFLAGS += -Ilib/cimarron/ -DREAL_SILICON
+
obj-$(CONFIG_FB_GEODE_GX1) += gx1fb.o
obj-$(CONFIG_FB_GEODE_GX) += gxfb.o
+obj-$(CONFIG_FB_GEODE_LX) += geodefb_lx.o
+obj-$(CONFIG_FB_GEODE_ACCEL) += geodefb_lx_accel.o
gx1fb-objs := gx1fb_core.o display_gx1.o video_cs5530.o
gxfb-objs := gxfb_core.o display_gx.o video_gx.o
+geodefb_lx-objs := geodefb_modes.o geodefb_hw.o
diff -Nru kernel-2.6.18geode-hurricane.orig/include/linux/vt_kern.h kernel-2.6.18geode-hurricane/include/linux/vt_kern.h
--- kernel-2.6.18geode-hurricane.orig/include/linux/vt_kern.h 2006-09-20 05:42:06.000000000 +0200
+++ kernel-2.6.18geode-hurricane/include/linux/vt_kern.h 2006-12-01 13:21:21.000000000 +0100
@@ -83,4 +83,10 @@
extern char con_buf[CON_BUF_SIZE];
extern struct semaphore con_buf_sem;
+/* Called when we switch KD_TEXT in vt_ioctl */
+#define CONSOLE_EVENT_SWITCH_TEXT 0x01
+
+/* Called when we switch to KD_GRaPHICS in vt_ioctl */
+#define CONSOLE_EVENT_SWITCH_GRAPHICS 0x02
+
#endif /* _VT_KERN_H */
diff -Nru kernel-2.6.18geode-hurricane.orig/lib/cimarron/build_num.h kernel-2.6.18geode-hurricane/lib/cimarron/build_num.h
--- kernel-2.6.18geode-hurricane.orig/lib/cimarron/build_num.h 1970-01-01 01:00:00.000000000 +0100
+++ kernel-2.6.18geode-hurricane/lib/cimarron/build_num.h 2006-12-01 13:21:21.000000000 +0100
@@ -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 -Nru kernel-2.6.18geode-hurricane.orig/lib/cimarron/cim/cimarron.c kernel-2.6.18geode-hurricane/lib/cimarron/cim/cimarron.c
--- kernel-2.6.18geode-hurricane.orig/lib/cimarron/cim/cimarron.c 1970-01-01 01:00:00.000000000 +0100
+++ kernel-2.6.18geode-hurricane/lib/cimarron/cim/cimarron.c 2006-12-01 13:21:21.000000000 +0100
@@ -0,0 +1,222 @@
+ /*
+ *
+ * Copyright (C) 2005 Advanced Micro Devices, Inc. All Rights Reserved.
+ *
+ *
+ *
+ *
+ *
+ *
+ * Base include file for the Cimarron library. This file should be modified
+ * and included in any Cimarron-based project.
+ *
+ *
+ */
+
+/*----------------------------------------------------------------------*/
+/* MODULE SETTINGS */
+/* The following #defines affect which modules are included in the */
+/* project. */
+/*----------------------------------------------------------------------*/
+
+#define CIMARRON_INCLUDE_GP 1
+#define CIMARRON_INCLUDE_VG 1
+#define CIMARRON_INCLUDE_VIP 1
+#define CIMARRON_INCLUDE_VOP 1
+#define CIMARRON_INCLUDE_VIDEO 1
+#define CIMARRON_INCLUDE_INIT 1
+
+#define CIMARRON_INCLUDE_VG_READ_ROUTINES 1
+#define CIMARRON_INCLUDE_DF_READ_ROUTINES 1
+#define CIMARRON_INCLUDE_VIP_READ_ROUTINES 1
+#define CIMARRON_INCLUDE_VOP_READ_ROUTINES 1
+
+/*----------------------------------------------------------------------*/
+/* HARDWARE ACCESS SETTINGS */
+/* The following #defines affect how the Cimarron macros access the */
+/* hardware. The hardware access macros are broken up into groups. */
+/* Each group includes an enabling #define as well as several #define */
+/* options that modify the macro configuration that is included. */
+/* If the enabling define is deleted or all options are set to 0, the */
+/* corresponding macros must be implemented by the user. The */
+/* combinations are explained as follows: */
+/* must be manually defined by the user. This allows a user to use the */
+/* cim_defs.h file for only those macros that suit the needs of his/her */
+/* project. For example, a user may need custom implementations of the */
+/* I/O and MSR macros, but may still want to use the default macros to */
+/* read and write hardware registers. The combinations are explained as */
+/* follows: */
+/* */
+/* Register Group: */
+/* Disabling define: */
+/* CIMARRON_EXCLUDE_REGISTER_ACCESS_MACROS */
+/* Define this setting to exclude the register access macros. */
+/* This setting is the inverse of the other group settings in */
+/* that these macros are included by default. This allows the */
+/* cim_defs.h file to be included outside of cimarron.c for */
+/* basic operations. */
+/* */
+/* Memory Group: */
+/* Enabling define: */
+/* CIMARRON_INCLUDE_STRING_MACROS */
+/* Options: */
+/* CIMARRON_OPTIMIZE_ASSEMBLY */
+/* Set to 1 to allow the use of inline assembly when writing */
+/* large chunks of data to memory. Essentially, this allows */
+/* a rep movsd in place of a slower C for-loop. */
+/* CIMARRON_OPTIMIZE_FORLOOP */
+/* Define for C only data writes. */
+/* */
+/* MSR Group: */
+/* Enabling define: */
+/* CIMARRON_INCLUDE_MSR_MACROS */
+/* Options: */
+/* CIMARRON_MSR_DIRECT_ASM */
+/* Set to 1 to allow the use of the rdmsr and wrmsr opcodes in */
+/* inline assembly. */
+/* CIMARRON_MSR_VSA_IO */
+/* Set to 1 to access MSRs using a VSAII virtual register. */
+/* CIMARRON_MSR_KERNEL_ROUTINE */
+/* Set to 1 to access MSRs using a wrapper routine in the */
+/* Linux kernel. */
+/* */
+/* IO Group: */
+/* Enabling define: */
+/* CIMARRON_INCLUDE_IO_MACROS */
+/* Options: */
+/* CIMARRON_IO_DIRECT_ACCESS */
+/* Set to 1 to perform IO accesses using inline assembly. */
+/* CIMARRON_IO_ABSTRACTED_ASM */
+/* Set to 1 to perform IO using abstracted IO in Linux. */
+/* */
+/* Custom Group: */
+/* Disabling define: */
+/* CIMARRON_EXCLUDE_CUSTOM_MACROS */
+/* By default, the custom macros (the macros used by */
+/* gp_custom_convert_blt) are mapped to the normal command */
+/* string macros. Setting this to 1 allows the user to */
+/* create a custom implementation. */
+/*----------------------------------------------------------------------*/
+
+/* UNCOMMENT THE FOLLOWING LINE TO EXCLUDE BASIC REGISTER ACCESS MACROS */
+
+/* #define CIMARRON_EXCLUDE_REGISTER_ACCESS_MACROS */
+
+#define CIMARRON_INCLUDE_STRING_MACROS
+#define CIMARRON_OPTIMIZE_ASSEMBLY 1
+#define CIMARRON_OPTIMIZE_FORLOOP 0
+#define CIMARRON_OPTIMIZE_ABSTRACTED_ASM 0
+
+#define CIMARRON_INCLUDE_MSR_MACROS
+#define CIMARRON_MSR_DIRECT_ASM 0
+#define CIMARRON_MSR_VSA_IO 1
+#define CIMARRON_MSR_ABSTRACTED_ASM 0
+#define CIMARRON_MSR_KERNEL_ROUTINE 0
+
+#define CIMARRON_INCLUDE_IO_MACROS
+#define CIMARRON_IO_DIRECT_ACCESS 1
+#define CIMARRON_IO_ABSTRACTED_ASM 0
+
+/* UNCOMMENT THE FOLLOWING LINE TO IMPLEMENT CUSTOM MACROS FOR GP_CUSTOM_CONVERT_BLT */
+
+/* #define CIMARRON_EXCLUDE_CUSTOM_MACROS */
+
+/*----------------------------------------------------------------------*/
+/* MODULE VARIABLES */
+/* The following #defines affect how global variables in each Cimarron */
+/* module are defined. These variables can be made static (to prevent */
+/* naming conflicts) or they can be defined without the static keyword */
+/* (to allow extern references). */
+/*----------------------------------------------------------------------*/
+
+#if 1
+#define CIMARRON_STATIC static
+#else
+#define CIMARRON_STATIC
+#endif
+
+/*----------------------------------------------------------------------*/
+/* CIMARRON GLOBAL VARIABLES */
+/* These globals are used by the hardware access macros. They must be */
+/* initialized by the application to point to the memory-mapped */
+/* registers of their respective blocks. */
+/*----------------------------------------------------------------------*/
+
+unsigned char *cim_gp_ptr = (unsigned char *)0;
+unsigned char *cim_fb_ptr = (unsigned char *)0;
+unsigned char *cim_cmd_base_ptr = (unsigned char *)0;
+unsigned char *cim_cmd_ptr = (unsigned char *)0;
+unsigned char *cim_vid_ptr = (unsigned char *)0;
+unsigned char *cim_vip_ptr = (unsigned char *)0;
+unsigned char *cim_vg_ptr = (unsigned char *)0;
+
+/*----------------------------------------------------------------------*/
+/* INCLUDE RELEVANT CIMARRON HEADERS */
+/*----------------------------------------------------------------------*/
+
+/* HARDWARE REGISTER DEFINITIONS */
+
+#include "cim_regs.h"
+
+/* ROUTINE DEFINITIONS */
+/* All routines have a prototype, even those that are not included */
+/* via #ifdefs. This prevents the user from having to include the */
+/* correct #defines anywhere he/she wants to call a Cimarron routine. */
+
+#include "cim_rtns.h"
+
+/* HARDWARE ACCESS MACROS */
+
+#include "cim_defs.h"
+
+/*----------------------------------------------------------------------*/
+/* CIMARRON MODULES */
+/* Modules and sub-modules are included based on user settings. Note */
+/* that excluding one or more modules may result in functionality */
+/* holes. */
+/*----------------------------------------------------------------------*/
+
+/* GRAPHICS PROCESSOR */
+
+#if CIMARRON_INCLUDE_GP
+#include "cim_gp.c"
+#endif
+
+/* VIDEO GENERATOR */
+
+#if CIMARRON_INCLUDE_VG
+#include "cim_modes.c"
+#include "cim_vg.c"
+#endif
+
+/* DISPLAY FILTER */
+
+#if CIMARRON_INCLUDE_VIDEO
+#include "cim_filter.c"
+#include "cim_df.c"
+#endif
+
+/* INITIALIZATION AND DETECTION */
+
+#if CIMARRON_INCLUDE_INIT
+#include "cim_init.c"
+#endif
+
+/* VIP SUPPORT */
+
+#if CIMARRON_INCLUDE_VIP
+#include "cim_vip.c"
+#endif
+
+/* VOP SUPPORT */
+
+#if CIMARRON_INCLUDE_VOP
+#include "cim_vop.c"
+#endif
+
+/* MSR ACCESS */
+/* This module is used to access machine-specific registers. */
+/* It cannot be excluded from a project. */
+
+#include "cim_msr.c"
+
diff -Nru kernel-2.6.18geode-hurricane.orig/lib/cimarron/cim/cim_defs.h kernel-2.6.18geode-hurricane/lib/cimarron/cim/cim_defs.h
--- kernel-2.6.18geode-hurricane.orig/lib/cimarron/cim/cim_defs.h 1970-01-01 01:00:00.000000000 +0100
+++ kernel-2.6.18geode-hurricane/lib/cimarron/cim/cim_defs.h 2006-12-01 13:21:21.000000000 +0100
@@ -0,0 +1,717 @@
+ /*
+ *
+ * Copyright (C) 2005 Advanced Micro Devices, Inc. All Rights Reserved.
+ *
+ *
+ *
+ *
+ *
+ *
+ * Cimarron hardware access macros.
+ *
+ *
+ */
+
+#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 -Nru kernel-2.6.18geode-hurricane.orig/lib/cimarron/cim/cim_df.c kernel-2.6.18geode-hurricane/lib/cimarron/cim/cim_df.c
--- kernel-2.6.18geode-hurricane.orig/lib/cimarron/cim/cim_df.c 1970-01-01 01:00:00.000000000 +0100
+++ kernel-2.6.18geode-hurricane/lib/cimarron/cim/cim_df.c 2006-12-01 13:21:21.000000000 +0100
@@ -0,0 +1,2544 @@
+ /*
+ *
+ * Copyright (C) 2005 Advanced Micro Devices, Inc. All Rights Reserved.
+ *
+ *
+ *
+ *
+ *
+ *
+ * Cimarron display filter routines. These routines program the video hardware.
+ *
+ *
+ */
+
+/*---------------------------------------------------------------------------
+ * 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 -Nru kernel-2.6.18geode-hurricane.orig/lib/cimarron/cim/cim_filter.c kernel-2.6.18geode-hurricane/lib/cimarron/cim/cim_filter.c
--- kernel-2.6.18geode-hurricane.orig/lib/cimarron/cim/cim_filter.c 1970-01-01 01:00:00.000000000 +0100
+++ kernel-2.6.18geode-hurricane/lib/cimarron/cim/cim_filter.c 2006-12-01 13:21:21.000000000 +0100
@@ -0,0 +1,533 @@
+ /*
+ *
+ * Copyright (C) 2005 Advanced Micro Devices, Inc. All Rights Reserved.
+ *
+ *
+ *
+ *
+ *
+ *
+ * Cimarron default video coefficients.
+ *
+ *
+ */
+
+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 -Nru kernel-2.6.18geode-hurricane.orig/lib/cimarron/cim/cim_gp.c kernel-2.6.18geode-hurricane/lib/cimarron/cim/cim_gp.c
--- kernel-2.6.18geode-hurricane.orig/lib/cimarron/cim/cim_gp.c 1970-01-01 01:00:00.000000000 +0100
+++ kernel-2.6.18geode-hurricane/lib/cimarron/cim/cim_gp.c 2006-12-01 13:21:21.000000000 +0100
@@ -0,0 +1,3442 @@
+ /*
+ *
+ * Copyright (C) 2005 Advanced Micro Devices, Inc. All Rights Reserved.
+ *
+ *
+ *
+ *
+ *
+ *
+ * Cimarron graphics processor routines. These routines program the graphics
+ * hardware using the graphics command buffer.
+ *
+ *
+ */
+
+/*---------------------*/
+/* 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 -Nru kernel-2.6.18geode-hurricane.orig/lib/cimarron/cim/cim_init.c kernel-2.6.18geode-hurricane/lib/cimarron/cim/cim_init.c
--- kernel-2.6.18geode-hurricane.orig/lib/cimarron/cim/cim_init.c 1970-01-01 01:00:00.000000000 +0100
+++ kernel-2.6.18geode-hurricane/lib/cimarron/cim/cim_init.c 2006-12-01 13:21:21.000000000 +0100
@@ -0,0 +1,209 @@
+ /*
+ *
+ * Copyright (C) 2005 Advanced Micro Devices, Inc. All Rights Reserved.
+ *
+ *
+ *
+ *
+ *
+ *
+ * Cimarron initialization routines. These routines detect a Geode LX and read
+ * all hardware base addresses.
+ *
+ *
+ */
+
+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 -Nru kernel-2.6.18geode-hurricane.orig/lib/cimarron/cim/cim_modes.c kernel-2.6.18geode-hurricane/lib/cimarron/cim/cim_modes.c
--- kernel-2.6.18geode-hurricane.orig/lib/cimarron/cim/cim_modes.c 1970-01-01 01:00:00.000000000 +0100
+++ kernel-2.6.18geode-hurricane/lib/cimarron/cim/cim_modes.c 2006-12-01 13:21:21.000000000 +0100
@@ -0,0 +1,1822 @@
+ /*
+ *
+ * Copyright (C) 2005 Advanced Micro Devices, Inc. All Rights Reserved.
+ *
+ *
+ *
+ *
+ *
+ *
+ * Cimarron mode tables.
+ *
+ *
+ */
+
+/*-------------------------------*/
+/* 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, -12 */
+ 0x3F479028, /* 40, 484, -12 */
+ 0x3F479427, /* 39, 485, -12 */
+ 0x3F479C25, /* 37, 487, -12 */
+ 0x3F47A024, /* 36, 488, -12 */
+ 0x3F47A822, /* 34, 490, -12 */
+ 0x3F47AC21, /* 33, 491, -12 */
+ 0x3F47B020, /* 32, 492, -12 */
+ 0x3F57B01F, /* 31, 492, -11 */
+ 0x3F57B81D, /* 29, 494, -11 */
+ 0x3F57BC1C, /* 28, 495, -11 */
+ 0x3F57C01B, /* 27, 496, -11 */
+ 0x3F57C41A, /* 26, 497, -11 */
+ 0x3F67C818, /* 24, 498, -10 */
+ 0x3F67CC17, /* 23, 499, -10 */
+ 0x3F67D016, /* 22, 500, -10 */
+ 0x3F67D415, /* 21, 501, -10 */
+ 0x3F67D814, /* 20, 502, -10 */
+ 0x3F77D813, /* 19, 502, -9 */
+ 0x3F77DC12, /* 18, 503, -9 */
+ 0x3F77E011, /* 17, 504, -9 */
+ 0x3F87E010, /* 16, 504, -8 */
+ 0x3F87E40F, /* 15, 505, -8 */
+ 0x3F87E80E, /* 14, 506, -8 */
+ 0x3F97E80D, /* 13, 506, -7 */
+ 0x3F97EC0C, /* 12, 507, -7 */
+ 0x3F97F00B, /* 11, 508, -7 */
+ 0x3FA7F00A, /* 10, 508, -6 */
+ 0x3FA7F409, /* 9, 509, -6 */
+ 0x3FB7F408, /* 8, 509, -5 */
+ 0x3FB7F408, /* 8, 509, -5 */
+ 0x3FC7F806, /* 6, 510, -4 */
+ 0x3FC7F806, /* 6, 510, -4 */
+ 0x3FD7F805, /* 5, 510, -3 */
+ 0x3FD7FC04, /* 4, 511, -3 */
+ 0x3FE7FC03, /* 3, 511, -2 */
+ 0x3FE7FC03, /* 3, 511, -2 */
+ 0x3FF7FC02, /* 2, 511, -1 */
+ 0x3FF7FC02, /* 2, 511, -1 */
+ 0x0007FC01, /* 1, 511, 0 */
+ 0x0007FC01, /* 1, 511, 0 */
+ 0x0007FC01, /* 1, 511, 0 */
+ 0x0027FFFF, /* -1, 511, 2 */
+ 0x0027FFFF, /* -1, 511, 2 */
+ 0x0037FFFE, /* -2, 511, 3 */
+ 0x0037FFFE, /* -2, 511, 3 */
+ 0x0047FFFD, /* -3, 511, 4 */
+ 0x0047FBFE, /* -2, 510, 4 */
+ 0x0057FBFD, /* -3, 510, 5 */
+ 0x0067FBFC, /* -4, 510, 6 */
+ 0x0077F7FC, /* -4, 509, 7 */
+ 0x0077F7FC, /* -4, 509, 7 */
+ 0x0087F7FB, /* -5, 509, 8 */
+ 0x0097F3FB, /* -5, 508, 9 */
+ 0x00A7F3FA, /* -6, 508, 10 */
+ 0x00B7EFFA, /* -6, 507, 11 */
+ 0x00C7EBFA, /* -6, 506, 12 */
+ 0x00D7EBF9, /* -7, 506, 13 */
+ 0x00E7E7F9, /* -7, 505, 14 */
+ 0x00F7E3F9, /* -7, 504, 15 */
+ 0x0107E3F8, /* -8, 504, 16 */
+ 0x0117DFF8, /* -8, 503, 17 */
+ 0x0127DBF8, /* -8, 502, 18 */
+ 0x0137DBF7, /* -9, 502, 19 */
+ 0x0147D7F7, /* -9, 501, 20 */
+ 0x0157D3F7, /* -9, 500, 21 */
+ 0x0167CFF7, /* -9, 499, 22 */
+ 0x0177CBF7, /* -9, 498, 23 */
+ 0x0197C7F6, /* -10, 497, 25 */
+ 0x01A7C3F6, /* -10, 496, 26 */
+ 0x01B7BFF6, /* -10, 495, 27 */
+ 0x01C7BBF6, /* -10, 494, 28 */
+ 0x01E7B3F6, /* -10, 492, 30 */
+ 0x01F7B3F5, /* -11, 492, 31 */
+ 0x0207AFF5, /* -11, 491, 32 */
+ 0x0217ABF5, /* -11, 490, 33 */
+ 0x0237A3F5, /* -11, 488, 35 */
+ 0x02479FF5, /* -11, 487, 36 */
+ 0x026797F5, /* -11, 485, 38 */
+ 0x027793F5, /* -11, 484, 39 */
+ 0x02978BF5, /* -11, 482, 41 */
+ 0x02A78BF4, /* -12, 482, 42 */
+ 0x02B787F4, /* -12, 481, 43 */
+ 0x02D77FF4, /* -12, 479, 45 */
+ 0x02F777F4, /* -12, 477, 47 */
+ 0x030773F4, /* -12, 476, 48 */
+ 0x03276BF4, /* -12, 474, 50 */
+ 0x033767F4, /* -12, 473, 51 */
+ 0x03575FF4, /* -12, 471, 53 */
+ 0x037757F4, /* -12, 469, 55 */
+ 0x038753F4, /* -12, 468, 56 */
+ 0x03A74BF4, /* -12, 466, 58 */
+ 0x03C743F4, /* -12, 464, 60 */
+ 0x03E73BF4, /* -12, 462, 62 */
+ 0x040737F3, /* -13, 461, 64 */
+ 0x04272FF3, /* -13, 459, 66 */
+ 0x044727F3, /* -13, 457, 68 */
+ 0x04671FF3, /* -13, 455, 70 */
+ 0x048717F3, /* -13, 453, 72 */
+ 0x04A70FF3, /* -13, 451, 74 */
+ 0x04C703F4, /* -12, 448, 76 */
+ 0x04D6FFF4, /* -12, 447, 77 */
+ 0x04F6F7F4, /* -12, 445, 79 */
+ 0x0516EFF4, /* -12, 443, 81 */
+ 0x0536E7F4, /* -12, 441, 83 */
+ 0x0556DFF4, /* -12, 439, 85 */
+ 0x0586CFF5, /* -11, 435, 88 */
+ 0x05A6C7F5, /* -11, 433, 90 */
+ 0x05C6BFF5, /* -11, 431, 92 */
+ 0x05F6B7F4, /* -12, 429, 95 */
+ 0x0616AFF4, /* -12, 427, 97 */
+ 0x0636A3F5, /* -11, 424, 99 */
+ 0x06569BF5, /* -11, 422, 101 */
+ 0x06868FF5, /* -11, 419, 104 */
+ 0x06A687F5, /* -11, 417, 106 */
+ 0x06C67FF5, /* -11, 415, 108 */
+ 0x06E677F5, /* -11, 413, 110 */
+ 0x07166BF5, /* -11, 410, 113 */
+ 0x073663F5, /* -11, 408, 115 */
+ 0x07665BF4, /* -12, 406, 118 */
+ 0x07964BF5, /* -11, 402, 121 */
+ 0x07B643F5, /* -11, 400, 123 */
+ 0x07D637F6, /* -10, 397, 125 */
+ 0x08062BF6, /* -10, 394, 128 */
+ 0x082623F6, /* -10, 392, 130 */
+ 0x085617F6, /* -10, 389, 133 */
+ 0x08760FF6, /* -10, 387, 135 */
+ 0x08B603F5, /* -11, 384, 139 */
+ 0x08D5F7F6, /* -10, 381, 141 */
+ 0x0905EBF6, /* -10, 378, 144 */
+ 0x0925E3F6, /* -10, 376, 146 */
+ 0x0955D3F7, /* -9, 372, 149 */
+ 0x0985C7F7, /* -9, 369, 152 */
+ 0x09A5BFF7, /* -9, 367, 154 */
+ 0x09D5B3F7, /* -9, 364, 157 */
+ 0x0A05ABF6, /* -10, 362, 160 */
+ 0x0A359BF7, /* -9, 358, 163 */
+ 0x0A658FF7, /* -9, 355, 166 */
+ 0x0A9587F6, /* -10, 353, 169 */
+ 0x0AB57BF7, /* -9, 350, 171 */
+ 0x0AE56FF7, /* -9, 347, 174 */
+ 0x0B1563F7, /* -9, 344, 177 */
+ 0x0B455BF6, /* -10, 342, 180 */
+ 0x0B754BF7, /* -9, 338, 183 */
+ 0x0BA53FF7, /* -9, 335, 186 */
+ 0x0BD533F7, /* -9, 332, 189 */
+ 0x0C0523F8, /* -8, 328, 192 */
+ 0x0C251BF8, /* -8, 326, 194 */
+ 0x0C550FF8, /* -8, 323, 197 */
+ 0x0C9503F7, /* -9, 320, 201 */
+ 0x0CC4F7F7, /* -9, 317, 204 */
+ 0x0CF4EBF7, /* -9, 314, 207 */
+ 0x0D24DBF8, /* -8, 310, 210 */
+ 0x0D54CFF8, /* -8, 307, 213 */
+ 0x0D84C3F8, /* -8, 304, 216 */
+ 0x0DB4BBF7, /* -9, 302, 219 */
+ 0x0DE4AFF7, /* -9, 299, 222 */
+ 0x0E149FF8, /* -8, 295, 225 */
+ 0x0E4493F8, /* -8, 292, 228 */
+ 0x0E7483F9, /* -7, 288, 231 */
+ 0x0EA477F9, /* -7, 285, 234 */
+ 0x0ED46BF9, /* -7, 282, 237 */
+ 0x0F045FF9, /* -7, 279, 240 */
+ 0x0F4453F8, /* -8, 276, 244 */
+ 0x0F7447F8, /* -8, 273, 247 */
+ 0x0FA43BF8, /* -8, 270, 250 */
+ 0x0FD42BF9, /* -7, 266, 253 */
+ 0x10041FF9, /* -7, 263, 256 */
+};
diff -Nru kernel-2.6.18geode-hurricane.orig/lib/cimarron/cim/cim_msr.c kernel-2.6.18geode-hurricane/lib/cimarron/cim/cim_msr.c
--- kernel-2.6.18geode-hurricane.orig/lib/cimarron/cim/cim_msr.c 1970-01-01 01:00:00.000000000 +0100
+++ kernel-2.6.18geode-hurricane/lib/cimarron/cim/cim_msr.c 2006-12-01 13:21:21.000000000 +0100
@@ -0,0 +1,379 @@
+ /*
+ *
+ * Copyright (C) 2005 Advanced Micro Devices, Inc. All Rights Reserved.
+ *
+ *
+ *
+ *
+ *
+ *
+ * Cimarron MSR access routines. These routines allow the user to query the
+ * state of the GeodeLink Bus and read and write model-specfic registers.
+ *
+ *
+ */
+
+/*--------------------------------------------------------------*/
+/* MSR GLOBALS */
+/* These variables hold a local copy of the GeodeLink mapping */
+/* as well as a lookup table for easy device addressing. */
+/*--------------------------------------------------------------*/
+
+GEODELINK_NODE gliu_nodes[24];
+GEODELINK_NODE msr_dev_lookup[MSR_DEVICE_EMPTY];
+
+#define GET_DEVICE_ID(macrohigh, macrolow) ((macrolow >> 12) & 0xFF)
+
+/*---------------------------------------------------------------------------
+ * msr_init_table
+ *
+ * This routine intializes the internal MSR table in Cimarron. This table is
+ * used for any MSR device accesses.
+ *---------------------------------------------------------------------------*/
+
+int msr_init_table (void)
+{
+ Q_WORD msr_value;
+ unsigned int i, j;
+ int return_value = CIM_STATUS_OK;
+
+ /* CHECK FOR VALID GEODELINK CONFIGURATION */
+ /* The CPU and the three GLIUs are assumed to be at known static addresses, so */
+ /* we will check the device IDs at these addresses as proof of a valid */
+ /* GeodeLink configuration */
+
+ MSR_READ (MSR_GEODELINK_CAP, MSR_ADDRESS_VAIL, &msr_value);
+ if (GET_DEVICE_ID (msr_value.high, msr_value.low) != MSR_CLASS_CODE_VAIL)
+ return_value = CIM_STATUS_ERROR;
+
+ MSR_READ (MSR_GEODELINK_CAP, MSR_ADDRESS_GLIU0, &msr_value);
+ if (GET_DEVICE_ID (msr_value.high, msr_value.low) != MSR_CLASS_CODE_GLIU)
+ return_value = CIM_STATUS_ERROR;
+
+ MSR_READ (MSR_GEODELINK_CAP, MSR_ADDRESS_GLIU1, &msr_value);
+ if (GET_DEVICE_ID (msr_value.high, msr_value.low) != MSR_CLASS_CODE_GLIU)
+ return_value = CIM_STATUS_ERROR;
+
+ MSR_READ (MSR_GEODELINK_CAP, MSR_ADDRESS_GLIU2, &msr_value);
+ if (GET_DEVICE_ID (msr_value.high, msr_value.low) != MSR_CLASS_CODE_GLIU)
+ return_value = CIM_STATUS_ERROR;
+
+ if (return_value == CIM_STATUS_OK)
+ {
+ /* BUILD LOCAL COPY OF THE GEODELINK BUS */
+
+ msr_create_geodelink_table (gliu_nodes);
+
+ /* CLEAR TABLE STATUS */
+
+ for (i = 0; i < MSR_DEVICE_EMPTY; i++)
+ msr_dev_lookup[i].device_id = MSR_DEVICE_NOTFOUND;
+
+ /* CREATE EASY LOOKUP TABLE FOR FUTURE HARDWARE ACCESS */
+ /* Note that MSR_DEVICE_EMPTY is the index after the last */
+ /* available device. Also note that we fill in known */
+ /* devices before filling in the rest of the table. */
+
+ msr_dev_lookup[MSR_DEVICE_GEODELX_GLIU0].address_from_cpu = MSR_ADDRESS_GLIU0;
+ msr_dev_lookup[MSR_DEVICE_GEODELX_GLIU0].device_id = MSR_DEVICE_PRESENT;
+ msr_dev_lookup[MSR_DEVICE_GEODELX_GLIU1].address_from_cpu = MSR_ADDRESS_GLIU1;
+ msr_dev_lookup[MSR_DEVICE_GEODELX_GLIU1].device_id = MSR_DEVICE_PRESENT;
+ msr_dev_lookup[MSR_DEVICE_5535_GLIU].address_from_cpu = MSR_ADDRESS_GLIU2;
+ msr_dev_lookup[MSR_DEVICE_5535_GLIU].device_id = MSR_DEVICE_PRESENT;
+ msr_dev_lookup[MSR_DEVICE_GEODELX_VAIL].address_from_cpu = MSR_ADDRESS_VAIL;
+ msr_dev_lookup[MSR_DEVICE_GEODELX_VAIL].device_id = MSR_DEVICE_PRESENT;
+
+ for (i = 0; i < MSR_DEVICE_EMPTY; i++)
+ {
+ if (msr_dev_lookup[i].device_id == MSR_DEVICE_NOTFOUND)
+ {
+ for (j = 0; j < 24; j++)
+ {
+ if (gliu_nodes[j].device_id == i)
+ break;
+ }
+
+ if (j == 24)
+ msr_dev_lookup[i].device_id = MSR_DEVICE_NOTFOUND;
+ else
+ {
+ msr_dev_lookup[i].device_id = MSR_DEVICE_PRESENT;
+ msr_dev_lookup[i].address_from_cpu = gliu_nodes[j].address_from_cpu;
+ }
+ }
+ }
+ }
+ else
+ {
+ /* ERROR OUT THE GEODELINK TABLES */
+
+ for (i = 0; i < 24; i++)
+ {
+ gliu_nodes[i].address_from_cpu = 0xFFFFFFFF;
+ gliu_nodes[i].device_id = MSR_DEVICE_EMPTY;
+ }
+
+ for (i = 0; i < MSR_DEVICE_EMPTY; i++)
+ {
+ msr_dev_lookup[i].address_from_cpu = 0xFFFFFFFF;
+ msr_dev_lookup[i].device_id = MSR_DEVICE_NOTFOUND;
+ }
+ }
+ return return_value;
+}
+
+/*---------------------------------------------------------------------------
+ * msr_create_geodelink_table
+ *
+ * This routine dumps the contents of the GeodeLink bus into an array of
+ * 24 GEODELINK_NODE structures. Indexes 0-7 represent ports 0-7 of GLIU0,
+ * indexes 8-15 represent ports 0-7 of GLIU1 and indexes 16-23 represent
+ * ports 0-7 of GLIU2 (5535).
+ *---------------------------------------------------------------------------*/
+
+int msr_create_geodelink_table (GEODELINK_NODE *gliu_nodes)
+{
+ unsigned long mbiu_port_count, reflective;
+ unsigned long port, index;
+ unsigned long gliu_count = 0;
+ int glcp_count = 0;
+ int usb_count = 0;
+ int mpci_count = 0;
+ Q_WORD msr_value;
+
+ /* ALL THREE GLIUS ARE IN ONE ARRAY */
+ /* Entries 0-7 contain the port information for GLIU0, entries */
+ /* 8-15 contain GLIU1 and 15-23 contain GLIU2. We perform the */
+ /* enumeration in two passes. The first simply fills in the */
+ /* addresses and class codes at each node. The second pass */
+ /* translates the class codes into indexes into Cimarron's device */
+ /* lookup table. */
+
+ /* COUNT GLIU0 PORTS */
+
+ MSR_READ (MSR_GLIU_CAP, MSR_ADDRESS_GLIU0, &msr_value);
+ mbiu_port_count = (msr_value.high >> NUM_PORTS_SHIFT) & 7;
+
+ /* FIND REFLECTIVE PORT */
+ /* Query the GLIU for the port through which we are communicating. */
+ /* We will avoid accesses to this port to avoid a self-reference. */
+
+ MSR_READ (MSR_GLIU_WHOAMI, MSR_ADDRESS_GLIU0, &msr_value);
+ reflective = msr_value.low & WHOAMI_MASK;
+
+ /* SPECIAL CASE FOR PORT 0 */
+ /* GLIU0 port 0 is a special case, as it points back to GLIU0. GLIU0 */
+ /* responds at address 0x10000xxx, which does not equal 0 << 29. */
+
+ gliu_nodes[0].address_from_cpu = MSR_ADDRESS_GLIU0;
+ gliu_nodes[0].device_id = MSR_CLASS_CODE_GLIU;
+
+ /* ENUMERATE ALL PORTS */
+
+ for (port = 1; port < 8; port++)
+ {
+ /* FILL IN ADDRESS */
+
+ gliu_nodes[port].address_from_cpu = port << 29;
+
+ if (port == reflective)
+ gliu_nodes[port].device_id = MSR_CLASS_CODE_REFLECTIVE;
+ else if (port > mbiu_port_count)
+ gliu_nodes[port].device_id = MSR_CLASS_CODE_UNPOPULATED;
+ else
+ {
+ MSR_READ (MSR_GEODELINK_CAP, gliu_nodes[port].address_from_cpu, &msr_value);
+ gliu_nodes[port].device_id = GET_DEVICE_ID (msr_value.high, msr_value.low);
+ }
+ }
+
+ /* COUNT GLIU1 PORTS */
+
+ MSR_READ (MSR_GLIU_CAP, MSR_ADDRESS_GLIU1, &msr_value);
+ mbiu_port_count = (msr_value.high >> NUM_PORTS_SHIFT) & 7;
+
+ /* FIND REFLECTIVE PORT */
+
+ MSR_READ (MSR_GLIU_WHOAMI, MSR_ADDRESS_GLIU1, &msr_value);
+ reflective = msr_value.low & WHOAMI_MASK;
+
+ /* ENUMERATE ALL PORTS */
+
+ for (port = 0; port < 8; port++)
+ {
+ index = port + 8;
+
+ /* FILL IN ADDRESS */
+
+ gliu_nodes[index].address_from_cpu = (0x02l << 29) + (port << 26);
+
+ if (port == reflective)
+ gliu_nodes[index].device_id = MSR_CLASS_CODE_REFLECTIVE;
+ else if (port > mbiu_port_count)
+ gliu_nodes[index].device_id = MSR_CLASS_CODE_UNPOPULATED;
+ else
+ {
+ MSR_READ (MSR_GEODELINK_CAP, gliu_nodes[index].address_from_cpu, &msr_value);
+ gliu_nodes[index].device_id = GET_DEVICE_ID (msr_value.high, msr_value.low);
+ }
+ }
+
+ /* COUNT GLIU2 PORTS */
+
+ MSR_READ (MSR_GLIU_CAP, MSR_ADDRESS_GLIU2, &msr_value);
+ mbiu_port_count = (msr_value.high >> NUM_PORTS_SHIFT) & 7;
+
+ /* FIND REFLECTIVE PORT */
+
+ MSR_READ (MSR_GLIU_WHOAMI, MSR_ADDRESS_GLIU2, &msr_value);
+ reflective = msr_value.low & WHOAMI_MASK;
+
+ /* FILL IN PORT 0 AND 1 */
+ /* Port 0 on 5535 is MBIU2. Port 1 is MPCI, but it is referenced at */
+ /* a special address. */
+
+ gliu_nodes[16].address_from_cpu = MSR_ADDRESS_GLIU2;
+ gliu_nodes[16].device_id = MSR_CLASS_CODE_GLIU;
+
+ gliu_nodes[17].address_from_cpu = MSR_ADDRESS_5535MPCI;
+ gliu_nodes[17].device_id = MSR_CLASS_CODE_MPCI;
+
+ /* ENUMERATE ALL PORTS */
+
+ for (port = 2; port < 8; port++)
+ {
+ index = port + 16;
+
+ /* FILL IN ADDRESS */
+
+ gliu_nodes[index].address_from_cpu =
+ (0x02l << 29) + (0x04l << 26) + (0x02l << 23) + (port << 20);
+
+ if (port == reflective)
+ gliu_nodes[index].device_id = MSR_CLASS_CODE_REFLECTIVE;
+ else if (port > mbiu_port_count)
+ gliu_nodes[index].device_id = MSR_CLASS_CODE_UNPOPULATED;
+ else
+ {
+ MSR_READ (MSR_GEODELINK_CAP, gliu_nodes[index].address_from_cpu, &msr_value);
+ gliu_nodes[index].device_id = GET_DEVICE_ID (msr_value.high, msr_value.low);
+ }
+ }
+
+ /* SECOND PASS - TRANSLATION */
+ /* Now that the class codes for each device are stored in the */
+ /* array, we walk through the array and translate the class */
+ /* codes to table indexes. For class codes that have multiple */
+ /* instances, the table indexes are sequential. */
+
+ for (port = 0; port < 24; port++)
+ {
+ /* SPECIAL CASE FOR GLIU UNITS */
+ /* A GLIU can be both on another port and on its own port. These */
+ /* end up as the same address, but are shown as duplicate nodes in */
+ /* the GeodeLink table. */
+
+ if ((port & 7) == 0)
+ gliu_count = port >> 3;
+
+ switch (gliu_nodes[port].device_id)
+ {
+ /* UNPOPULATED OR REFLECTIVE NODES */
+
+ case MSR_CLASS_CODE_UNPOPULATED: index = MSR_DEVICE_EMPTY; break;
+ case MSR_CLASS_CODE_REFLECTIVE: index = MSR_DEVICE_REFLECTIVE; break;
+
+ /* KNOWN CLASS CODES */
+
+ case MSR_CLASS_CODE_GLIU: index = MSR_DEVICE_GEODELX_GLIU0 + gliu_count++; break;
+ case MSR_CLASS_CODE_GLCP: index = MSR_DEVICE_GEODELX_GLCP + glcp_count++; break;
+ case MSR_CLASS_CODE_MPCI: index = MSR_DEVICE_GEODELX_MPCI + mpci_count++; break;
+ case MSR_CLASS_CODE_USB: index = MSR_DEVICE_5535_USB2 + usb_count++; break;
+ case MSR_CLASS_CODE_USB2: index = MSR_DEVICE_5536_USB_2_0; break;
+ case MSR_CLASS_CODE_ATAC: index = MSR_DEVICE_5535_ATAC; break;
+ case MSR_CLASS_CODE_MDD: index = MSR_DEVICE_5535_MDD; break;
+ case MSR_CLASS_CODE_ACC: index = MSR_DEVICE_5535_ACC; break;
+ case MSR_CLASS_CODE_MC: index = MSR_DEVICE_GEODELX_MC; break;
+ case MSR_CLASS_CODE_GP: index = MSR_DEVICE_GEODELX_GP; break;
+ case MSR_CLASS_CODE_VG: index = MSR_DEVICE_GEODELX_VG; break;
+ case MSR_CLASS_CODE_DF: index = MSR_DEVICE_GEODELX_DF; break;
+ case MSR_CLASS_CODE_FG: index = MSR_DEVICE_GEODELX_FG; break;
+ case MSR_CLASS_CODE_VIP: index = MSR_DEVICE_GEODELX_VIP; break;
+ case MSR_CLASS_CODE_AES: index = MSR_DEVICE_GEODELX_AES; break;
+ case MSR_CLASS_CODE_VAIL: index = MSR_DEVICE_GEODELX_VAIL; break;
+ default: index = MSR_DEVICE_EMPTY; break;
+ }
+
+ gliu_nodes[port].device_id = index;
+ }
+
+ return CIM_STATUS_OK;
+}
+
+/*---------------------------------------------------------------------------
+ * msr_create_device_list
+ *
+ * This routine dumps a list of all known GeodeLX/5535 devices as well as their
+ * respective status and address.
+ *---------------------------------------------------------------------------*/
+
+int msr_create_device_list (GEODELINK_NODE *gliu_nodes, int max_devices)
+{
+ int i, count;
+
+ if (max_devices < MSR_DEVICE_EMPTY) count = max_devices;
+ else count = MSR_DEVICE_EMPTY;
+
+ for (i = 0; i < count; i++)
+ {
+ gliu_nodes[i].address_from_cpu = msr_dev_lookup[i].address_from_cpu;
+ gliu_nodes[i].device_id = msr_dev_lookup[i].device_id;
+ }
+
+ return CIM_STATUS_OK;
+}
+
+/*--------------------------------------------------------------------
+ * msr_read64
+ *
+ * Performs a 64-bit read from 'msr_register' in device 'device'. 'device' is
+ * an index into Cimarron's table of known GeodeLink devices.
+ *-------------------------------------------------------------------*/
+
+int msr_read64 (unsigned long device, unsigned long msr_register,
+ Q_WORD *msr_value)
+{
+ if (device < MSR_DEVICE_EMPTY)
+ {
+ if (msr_dev_lookup[device].device_id == MSR_DEVICE_PRESENT)
+ {
+ MSR_READ (msr_register, msr_dev_lookup[device].address_from_cpu, msr_value);
+ return CIM_STATUS_OK;
+ }
+ }
+
+ msr_value->low = msr_value->high = 0;
+ return CIM_STATUS_DEVNOTFOUND;
+}
+
+/*--------------------------------------------------------------------
+ * msr_write64
+ *
+ * Performs a 64-bit write to 'msr_register' in device 'device'. 'device' is
+ * an index into Cimarron's table of known GeodeLink devices.
+ *-------------------------------------------------------------------*/
+
+int msr_write64 (unsigned long device, unsigned long msr_register,
+ Q_WORD *msr_value)
+{
+ if (device < MSR_DEVICE_EMPTY)
+ {
+ if (msr_dev_lookup[device].device_id == MSR_DEVICE_PRESENT)
+ {
+ MSR_WRITE (msr_register, msr_dev_lookup[device].address_from_cpu, msr_value);
+ return CIM_STATUS_OK;
+ }
+ }
+ return CIM_STATUS_DEVNOTFOUND;
+}
+
diff -Nru kernel-2.6.18geode-hurricane.orig/lib/cimarron/cim/cim_parm.h kernel-2.6.18geode-hurricane/lib/cimarron/cim/cim_parm.h
--- kernel-2.6.18geode-hurricane.orig/lib/cimarron/cim/cim_parm.h 1970-01-01 01:00:00.000000000 +0100
+++ kernel-2.6.18geode-hurricane/lib/cimarron/cim/cim_parm.h 2006-12-01 13:21:21.000000000 +0100
@@ -0,0 +1,1268 @@
+ /*
+ *
+ * Copyright (C) 2005 Advanced Micro Devices, Inc. All Rights Reserved.
+ *
+ *
+ *
+ *
+ *
+ *
+ * Cimarron user definitions.
+ *
+ *
+ */
+
+#ifndef _cim_parm_h
+#define _cim_parm_h
+
+/*===================================================*/
+/* CIMARRON RETURN VALUE DEFINITIONS */
+/*===================================================*/
+
+#define CIM_STATUS_OK 0x00000000
+#define CIM_STATUS_ERROR 0x00000001
+#define CIM_STATUS_INVALIDPARAMS 0x00000002
+#define CIM_STATUS_DEVNOTFOUND 0x00000004
+#define CIM_STATUS_INVALIDSCALE 0x00000008
+#define CIM_STATUS_INEXACTMATCH 0x00000010
+#define CIM_STATUS_NOLOCK 0x00000020
+#define CIM_STATUS_CPUNOTFOUND 0x00000040
+#define CIM_STATUS_DISPLAYUNAVAILABLE 0x00000080
+#define CIM_STATUS_NOTFOUND 0x00000100
+
+/*===================================================*/
+/* CIMARRON CPU DEFINITIONS */
+/*===================================================*/
+
+#define CIM_CPU_GEODEGX 0x00000001
+#define CIM_CPU_GEODELX 0x00000002
+
+#define CIM_SB_5535 0x00000001
+#define CIM_SB_5536 0x00000002
+
+/*===================================================*/
+/* MSR PARAMETERS */
+/*===================================================*/
+
+/*-------------------------------------------------------------*/
+/* GEODELINK DEVICE IDS */
+/* These values uniquely identify all known GeodeLink devices */
+/* in GeodeLX and its companion, 5535/6. For multiple devices */
+/* of the same class (GLIU, USB, etc.) the table order is used */
+/* to to identify the expected device order, in terms of on */
+/* which GLIU the device is found, and on which port. */
+/*-------------------------------------------------------------*/
+
+#define MSR_DEVICE_GEODELX_GLIU0 0x00
+#define MSR_DEVICE_GEODELX_GLIU1 0x01
+#define MSR_DEVICE_5535_GLIU 0x02
+#define MSR_DEVICE_GEODELX_GLCP 0x03
+#define MSR_DEVICE_5535_GLCP 0x04
+#define MSR_DEVICE_GEODELX_MPCI 0x05
+#define MSR_DEVICE_5535_MPCI 0x06
+#define MSR_DEVICE_GEODELX_MC 0x07
+#define MSR_DEVICE_GEODELX_GP 0x08
+#define MSR_DEVICE_GEODELX_VG 0x09
+#define MSR_DEVICE_GEODELX_VIP 0x0A
+#define MSR_DEVICE_GEODELX_AES 0x0B
+#define MSR_DEVICE_GEODELX_DF 0x0C
+#define MSR_DEVICE_GEODELX_FG 0x0D
+#define MSR_DEVICE_GEODELX_VAIL 0x0E
+#define MSR_DEVICE_5536_USB_2_0 0x0F
+#define MSR_DEVICE_5535_USB2 0x10
+#define MSR_DEVICE_5535_USB1 0x11
+#define MSR_DEVICE_5535_ATAC 0x12
+#define MSR_DEVICE_5535_MDD 0x13
+#define MSR_DEVICE_5535_ACC 0x14
+#define MSR_DEVICE_EMPTY 0x15
+#define MSR_DEVICE_REFLECTIVE 0x16
+#define MSR_DEVICE_PRESENT 0x17
+#define MSR_DEVICE_NOTFOUND 0x18
+
+/*---------------------------------------------*/
+/* GEODELINK TABLE ENTRY */
+/* The following structure represents one port */
+/* on a GeodeLink Interface Unit (GLIU) */
+/*---------------------------------------------*/
+
+typedef struct tagGeodeLinkNode
+{
+ unsigned long address_from_cpu;
+ unsigned long device_id;
+
+} GEODELINK_NODE;
+
+/*---------------------------------------------*/
+/* QWORD DATA STRUCTURE */
+/* 64-bit data structure for MSR acess. */
+/*---------------------------------------------*/
+
+typedef struct tagQ_WORD
+{
+ unsigned long high;
+ unsigned long low;
+
+} Q_WORD;
+
+/*===================================================*/
+/* INITIALIZATION USER PARAMETERS */
+/*===================================================*/
+
+typedef struct tagInitBaseAddresses
+{
+ unsigned long framebuffer_base;
+ unsigned long gp_register_base;
+ unsigned long vg_register_base;
+ unsigned long df_register_base;
+ unsigned long vip_register_base;
+ unsigned long framebuffer_size;
+
+} INIT_BASE_ADDRESSES;
+
+/*===================================================*/
+/* GP USER PARAMETER DEFINITIONS */
+/*===================================================*/
+
+/*---------------------------*/
+/* GP_DECLARE_BLT PARAMETERS */
+/*---------------------------*/
+
+#define CIMGP_BLTFLAGS_PRES_LUT 0x0001
+#define CIMGP_BLTFLAGS_PRES_COLOR_PAT 0x0002
+#define CIMGP_ENABLE_PREFETCH 0x0004
+#define CIMGP_BLTFLAGS_HAZARD 0x0008
+#define CIMGP_BLTFLAGS_INVERTMONO 0x0010
+#define CIMGP_BLTFLAGS_LIMITBUFFER 0x0020
+
+/*-----------------------------------*/
+/* GP_SET_ALPHA_OPERATION PARAMETERS */
+/*-----------------------------------*/
+
+#define CIMGP_APPLY_BLEND_TO_RGB 1
+#define CIMGP_APPLY_BLEND_TO_ALPHA 2
+#define CIMGP_APPLY_BLEND_TO_ALL 3
+
+#define CIMGP_ALPHA_TIMES_A 0
+#define CIMGP_BETA_TIMES_B 1
+#define CIMGP_A_PLUS_BETA_B 2
+#define CIMGP_ALPHA_A_PLUS_BETA_B 3
+
+#define CIMGP_CHANNEL_A_ALPHA 0
+#define CIMGP_CHANNEL_B_ALPHA 1
+#define CIMGP_CONSTANT_ALPHA 2
+#define CIMGP_ALPHA_EQUALS_ONE 3
+#define CIMGP_ALPHA_FROM_RGB_A 4
+#define CIMGP_ALPHA_FROM_RGB_B 5
+#define CIMGP_CONVERTED_ALPHA 6
+
+#define CIMGP_CHANNEL_A_SOURCE 0
+#define CIMGP_CHANNEL_A_DEST 1
+
+/*---------------------------------*/
+/* GP_SET_SOURCE_FORMAT PARAMETERS */
+/*---------------------------------*/
+
+#define CIMGP_SOURCE_FMT_3_3_2 0x00
+#define CIMGP_SOURCE_FMT_8BPP_INDEXED 0x01
+#define CIMGP_SOURCE_FMT_4_4_4_4 0x04
+#define CIMGP_SOURCE_FMT_12BPP_BGR 0x14
+#define CIMGP_SOURCE_FMT_1_5_5_5 0x05
+#define CIMGP_SOURCE_FMT_15BPP_BGR 0x15
+#define CIMGP_SOURCE_FMT_0_5_6_5 0x06
+#define CIMGP_SOURCE_FMT_16BPP_BGR 0x16
+#define CIMGP_SOURCE_FMT_YUYV 0x07
+#define CIMGP_SOURCE_FMT_UYVY 0x17
+#define CIMGP_SOURCE_FMT_8_8_8_8 0x08
+#define CIMGP_SOURCE_FMT_32BPP_BGR 0x18
+#define CIMGP_SOURCE_FMT_24BPP 0x0B
+#define CIMGP_SOURCE_FMT_4BPP_INDEXED 0x0D
+
+/*------------------------------------*/
+/* GP_SCREEN_TO_SCREEN_BLT PARAMETERS */
+/*------------------------------------*/
+
+#define CIMGP_NEGXDIR 1
+#define CIMGP_NEGYDIR 2
+
+/*------------------------------------*/
+/* GP_BRESENHAM_LINE PARAMETERS */
+/*------------------------------------*/
+
+#define CIMGP_YMAJOR 1
+#define CIMGP_POSMAJOR 2
+#define CIMGP_POSMINOR 4
+
+/*----------------------------------------------*/
+/* USER STRUCTURE FOR SAVING/RESTORING GP STATE */
+/*----------------------------------------------*/
+
+typedef struct tagGPSaveRestore
+{
+ unsigned long base_offset;
+ unsigned long cmd_top;
+ unsigned long cmd_bottom;
+ unsigned long cmd_base;
+ unsigned long cmd_read;
+
+} GP_SAVE_RESTORE;
+
+/*===================================================*/
+/* VG USER PARAMETER DEFINITIONS */
+/*===================================================*/
+
+/*-------------------------------------------*/
+/* SUPPORTED TV ENCODERS */
+/*-------------------------------------------*/
+
+#define VG_ENCODER_ADV7171 0x0001
+#define VG_ENCODER_SAA7127 0x0002
+#define VG_ENCODER_FS454 0x0003
+#define VG_ENCODER_ADV7300 0x0004
+
+/*-------------------------------------------*/
+/* SUPPORTED TV RESOLUTIONS */
+/*-------------------------------------------*/
+
+#define VG_TVMODE_NTSC 0x00000000
+#define VG_TVMODE_PAL 0x00000001
+#define VG_TVMODE_480P 0x00000002
+#define VG_TVMODE_720P 0x00000003
+#define VG_TVMODE_1080I 0x00000004
+#define VG_TVMODE_6X4_NTSC 0x00000005
+#define VG_TVMODE_8X6_NTSC 0x00000006
+#define VG_TVMODE_10X7_NTSC 0x00000007
+#define VG_TVMODE_6X4_PAL 0x00000008
+#define VG_TVMODE_8X6_PAL 0x00000009
+#define VG_TVMODE_10X7_PAL 0x0000000A
+
+/*-------------------------------------------*/
+/* USER STRUCTURE FOR SETTING A DISPLAY MODE */
+/*-------------------------------------------*/
+
+#define VG_SUPPORTFLAG_8BPP 0x00000001
+#define VG_SUPPORTFLAG_12BPP 0x00000002
+#define VG_SUPPORTFLAG_15BPP 0x00000004
+#define VG_SUPPORTFLAG_16BPP 0x00000008
+#define VG_SUPPORTFLAG_24BPP 0x00000010
+#define VG_SUPPORTFLAG_32BPP 0x00000020
+#define VG_SUPPORTFLAG_56HZ 0x00000040
+#define VG_SUPPORTFLAG_60HZ 0x00000080
+#define VG_SUPPORTFLAG_70HZ 0x00000100
+#define VG_SUPPORTFLAG_72HZ 0x00000200
+#define VG_SUPPORTFLAG_75HZ 0x00000400
+#define VG_SUPPORTFLAG_85HZ 0x00000800
+#define VG_SUPPORTFLAG_90HZ 0x00001000
+#define VG_SUPPORTFLAG_100HZ 0x00002000
+#define VG_SUPPORTFLAG_HZMASK 0x00003FC0
+#define VG_SUPPORTFLAG_ADV7171 0x00004000
+#define VG_SUPPORTFLAG_SAA7127 0x00008000
+#define VG_SUPPORTFLAG_FS454 0x00010000
+#define VG_SUPPORTFLAG_ADV7300 0x00020000
+#define VG_SUPPORTFLAG_ENCODERMASK 0x0003C000
+#define VG_SUPPORTFLAG_PANEL 0x00040000
+#define VG_SUPPORTFLAG_TVOUT 0x00080000
+#define VG_SUPPORTFLAG_NTSC 0x00000000
+#define VG_SUPPORTFLAG_PAL 0x00100000
+#define VG_SUPPORTFLAG_480P 0x00200000
+#define VG_SUPPORTFLAG_720P 0x00300000
+#define VG_SUPPORTFLAG_1080I 0x00400000
+#define VG_SUPPORTFLAG_6X4_NTSC 0x00500000
+#define VG_SUPPORTFLAG_8X6_NTSC 0x00600000
+#define VG_SUPPORTFLAG_10X7_NTSC 0x00700000
+#define VG_SUPPORTFLAG_6X4_PAL 0x00800000
+#define VG_SUPPORTFLAG_8X6_PAL 0x00900000
+#define VG_SUPPORTFLAG_10X7_PAL 0x00A00000
+#define VG_SUPPORTFLAG_TVMODEMASK 0x00F00000
+
+#define VG_MODEFLAG_NEG_HSYNC 0x00000001
+#define VG_MODEFLAG_NEG_VSYNC 0x00000002
+#define VG_MODEFLAG_INTERLACED 0x00000004
+#define VG_MODEFLAG_PANELOUT 0x00000008
+#define VG_MODEFLAG_CENTERED 0x00000010
+#define VG_MODEFLAG_LINEARPITCH 0x00000020
+#define VG_MODEFLAG_TVOUT 0x00000040
+#define VG_MODEFLAG_HALFCLOCK 0x00000080
+#define VG_MODEFLAG_QVGA 0x00000100
+#define VG_MODEFLAG_EXCLUDEPLL 0x00000200
+#define VG_MODEFLAG_NOPANELTIMINGS 0x00000400
+#define VG_MODEFLAG_XVGA_TFT 0x00000800
+#define VG_MODEFLAG_CUSTOM_PANEL 0x00001000
+#define VG_MODEFLAG_CRT_AND_FP 0x00002000
+#define VG_MODEFLAG_LOW_BAND 0x00000000
+#define VG_MODEFLAG_AVG_BAND 0x00004000
+#define VG_MODEFLAG_HIGH_BAND 0x00008000
+#define VG_MODEFLAG_LEGACY_BAND 0x0000C000
+#define VG_MODEFLAG_BANDWIDTHMASK 0x0000C000
+#define VG_MODEFLAG_OVERRIDE_BAND 0x00010000
+#define VG_MODEFLAG_INT_ADDRESS 0x00000000
+#define VG_MODEFLAG_INT_LINEDOUBLE 0x00020000
+#define VG_MODEFLAG_INT_FLICKER 0x00040000
+#define VG_MODEFLAG_INT_MASK 0x00060000
+#define VG_MODEFLAG_INT_OVERRIDE 0x00080000
+#define VG_MODEFLAG_INVERT_SHFCLK 0x00100000
+#define VG_MODEFLAG_MANUAL_FREQUENCY 0x00200000
+#define VG_MODEFLAG_PLL_BYPASS 0x00400000
+#define VG_MODEFLAG_VIP_TO_DOT_CLOCK 0x00800000
+
+#define VG_MODEFLAG_VALIDUSERFLAGS (VG_MODEFLAG_CRT_AND_FP | \
+ VG_MODEFLAG_XVGA_TFT | \
+ VG_MODEFLAG_NOPANELTIMINGS | \
+ VG_MODEFLAG_EXCLUDEPLL | \
+ VG_MODEFLAG_LINEARPITCH)
+
+typedef struct tagVGDisplayMode
+{
+ /* DISPLAY MODE FLAGS */
+ /* Includes BPP, refresh rate information, interlacing, etc. */
+
+ unsigned long internal_flags;
+ unsigned long flags;
+
+ /* SOURCE RESOLUTION */
+ /* The following values reflect the resolution of the data in the frame */
+ /* buffer. These values are used to enable scaling and filtering. */
+
+ unsigned long src_width;
+ unsigned long src_height;
+
+ /* PANEL SETTINGS */
+ /* These allow a user to set a panel mode through the vg_set_custom_mode */
+ /* routine. These values are only relevant if the VG_MODEFLAG_PANEL is */
+ /* also set. */
+
+ unsigned long mode_width;
+ unsigned long mode_height;
+ unsigned long panel_width;
+ unsigned long panel_height;
+ unsigned long panel_tim1;
+ unsigned long panel_tim2;
+ unsigned long panel_dither_ctl;
+ unsigned long panel_pad_sel_low;
+ unsigned long panel_pad_sel_high;
+
+ /* OUTPUT TIMINGS */
+ /* If the active width and height do not match the source */
+ /* dimensions the graphics data will be scaled. */
+
+ unsigned long hactive;
+ unsigned long hblankstart;
+ unsigned long hsyncstart;
+ unsigned long hsyncend;
+ unsigned long hblankend;
+ unsigned long htotal;
+
+ unsigned long vactive;
+ unsigned long vblankstart;
+ unsigned long vsyncstart;
+ unsigned long vsyncend;
+ unsigned long vblankend;
+ unsigned long vtotal;
+
+ unsigned long vactive_even;
+ unsigned long vblankstart_even;
+ unsigned long vsyncstart_even;
+ unsigned long vsyncend_even;
+ unsigned long vblankend_even;
+ unsigned long vtotal_even;
+
+ /* CLOCK FREQUENCY */
+
+ unsigned long frequency;
+
+} VG_DISPLAY_MODE;
+
+/*-------------------------------------------*/
+/* PLL FLAGS */
+/*-------------------------------------------*/
+
+#define VG_PLL_DIVIDE_BY_2 0x00000001
+#define VG_PLL_DIVIDE_BY_4 0x00000002
+#define VG_PLL_BYPASS 0x00000004
+#define VG_PLL_MANUAL 0x00000008
+#define VG_PLL_VIP_CLOCK 0x00000010
+
+/*-------------------------------------------*/
+/* USER STRUCTURE FOR QUERYING DISPLAY MODES */
+/*-------------------------------------------*/
+
+typedef struct tagQueryDisplayMode
+{
+ int interlaced;
+ int halfclock;
+ unsigned long active_width;
+ unsigned long active_height;
+ unsigned long panel_width;
+ unsigned long panel_height;
+ unsigned long total_width;
+ unsigned long total_height;
+ unsigned long bpp;
+ unsigned long hz;
+ unsigned long frequency;
+ unsigned long query_flags;
+ unsigned long encoder;
+ unsigned long tvmode;
+
+} VG_QUERY_MODE;
+
+/*-------------------------------------------*/
+/* USER STRUCTURE FOR QUERYING CURSOR DATA */
+/*-------------------------------------------*/
+
+typedef struct tagCursorData
+{
+ int enable;
+ int color_cursor;
+ unsigned long cursor_offset;
+ unsigned long cursor_x;
+ unsigned long cursor_y;
+ unsigned long clipx;
+ unsigned long clipy;
+ unsigned long mono_color0;
+ unsigned long mono_color1;
+ unsigned long flags;
+
+} VG_CURSOR_DATA;
+
+/*------------------------------------------------*/
+/* VG INTERRUPT STATUS SOURCES */
+/*------------------------------------------------*/
+
+#define VG_INT_LINE_MATCH 0x00010000
+#define VG_INT_VSYNC_LOSS 0x00020000
+
+/*------------------------------------------------*/
+/* USER STRUCTURE FOR SETTING COMPRESSION DATA */
+/*------------------------------------------------*/
+
+typedef struct tagCompressionData
+{
+ unsigned long compression_offset;
+ unsigned long pitch;
+ unsigned long size;
+ unsigned long flags;
+
+} VG_COMPRESSION_DATA;
+
+/*-------------------------------------------------*/
+/* USER STRUCTURE FOR CONFIGURING LINE INTERRUPTS */
+/*-------------------------------------------------*/
+
+typedef struct tagInterruptInfo
+{
+ unsigned long line;
+ unsigned long flags;
+ int enable;
+
+} VG_INTERRUPT_PARAMS;
+
+/*-------------------------------------------------*/
+/* USER STRUCTURE FOR PANNING THE DESKTOP */
+/*-------------------------------------------------*/
+
+typedef struct tagPanningInfo
+{
+ unsigned long start_x;
+ unsigned long start_y;
+ int start_updated;
+
+} VG_PANNING_COORDINATES;
+
+/*--------------------------------------------------*/
+/* USER STRUCTURE FOR SAVING/RESTORING THE VG STATE */
+/*--------------------------------------------------*/
+
+typedef struct tagVGSaveRestore
+{
+ /* VG REGISTERS */
+
+ unsigned long unlock;
+ unsigned long gcfg;
+ unsigned long dcfg;
+ unsigned long arb_cfg;
+ unsigned long fb_offset;
+ unsigned long cb_offset;
+ unsigned long cursor_offset;
+ unsigned long video_y_offset;
+ unsigned long video_u_offset;
+ unsigned long video_v_offset;
+ unsigned long dv_top;
+ unsigned long line_size;
+ unsigned long gfx_pitch;
+ unsigned long video_yuv_pitch;
+ unsigned long h_active;
+ unsigned long h_blank;
+ unsigned long h_sync;
+ unsigned long v_active;
+ unsigned long v_blank;
+ unsigned long v_sync;
+ unsigned long fb_active;
+ unsigned long cursor_x;
+ unsigned long cursor_y;
+ unsigned long vid_ds_delta;
+ unsigned long fb_base;
+ unsigned long dv_ctl;
+ unsigned long gfx_scale;
+ unsigned long irq_ctl;
+ unsigned long vbi_even_ctl;
+ unsigned long vbi_odd_ctl;
+ unsigned long vbi_hor_ctl;
+ unsigned long vbi_odd_line_enable;
+ unsigned long vbi_even_line_enable;
+ unsigned long vbi_pitch;
+ unsigned long color_key;
+ unsigned long color_key_mask;
+ unsigned long color_key_x;
+ unsigned long color_key_y;
+ unsigned long irq;
+ unsigned long genlk_ctl;
+ unsigned long vid_y_even_offset;
+ unsigned long vid_u_even_offset;
+ unsigned long vid_v_even_offset;
+ unsigned long vactive_even;
+ unsigned long vblank_even;
+ unsigned long vsync_even;
+ unsigned long h_coeff[512];
+ unsigned long v_coeff[256];
+ unsigned long palette[261];
+ unsigned long cursor_data[3072];
+ unsigned long dot_pll;
+ unsigned long pll_flags;
+
+ /* VG MSRS */
+
+ Q_WORD msr_cap;
+ Q_WORD msr_config;
+ Q_WORD msr_smi;
+ Q_WORD msr_error;
+ Q_WORD msr_pm;
+ Q_WORD msr_diag;
+ Q_WORD msr_spare;
+ Q_WORD msr_ram_ctl;
+
+} VG_SAVE_RESTORE;
+
+/*-------------------------------------------*/
+/* VG_GET_DISPLAY_MODE_INDEX PARAMETERS */
+/*-------------------------------------------*/
+
+#define VG_QUERYFLAG_ACTIVEWIDTH 0x00000001
+#define VG_QUERYFLAG_ACTIVEHEIGHT 0x00000002
+#define VG_QUERYFLAG_TOTALWIDTH 0x00000004
+#define VG_QUERYFLAG_TOTALHEIGHT 0x00000008
+#define VG_QUERYFLAG_BPP 0x00000010
+#define VG_QUERYFLAG_REFRESH 0x00000020
+#define VG_QUERYFLAG_PIXELCLOCK 0x00000040
+#define VG_QUERYFLAG_PIXELCLOCK_APPROX 0x00000080
+#define VG_QUERYFLAG_PANEL 0x00000100
+#define VG_QUERYFLAG_PANELWIDTH 0x00000200
+#define VG_QUERYFLAG_PANELHEIGHT 0x00000400
+#define VG_QUERYFLAG_TVOUT 0x00000800
+#define VG_QUERYFLAG_INTERLACED 0x00001000
+#define VG_QUERYFLAG_HALFCLOCK 0x00002000
+#define VG_QUERYFLAG_ENCODER 0x00004000
+#define VG_QUERYFLAG_TVMODE 0x00008000
+
+/*-----------------------------------------------*/
+/* VG FLICKER FILTER SETTINGS */
+/*-----------------------------------------------*/
+
+#define VG_FLICKER_FILTER_NONE 0x00000000
+#define VG_FLICKER_FILTER_1_16 0x10000000
+#define VG_FLICKER_FILTER_1_8 0x20000000
+#define VG_FLICKER_FILTER_1_4 0x40000000
+#define VG_FLICKER_FILTER_5_16 0x50000000
+#define VG_FLICKER_FILTER_MASK 0xF0000000
+
+/*-----------------------------------------------*/
+/* VG CRC SOURCES */
+/*-----------------------------------------------*/
+
+#define VG_CRC_SOURCE_PREFILTER 0x00000000
+#define VG_CRC_SOURCE_PREFLICKER 0x00000001
+#define VG_CRC_SOURCE_POSTFLICKER 0x00000002
+#define VG_CRC_SOURCE_PREFILTER_EVEN 0x00000010
+#define VG_CRC_SOURCE_PREFLICKER_EVEN 0x00000011
+#define VG_CRC_SOURCE_POSTFLICKER_EVEN 0x00000012
+#define VG_CRC_SOURCE_EVEN 0x00000010
+
+/*===================================================*/
+/* DISPLAY FILTER PARAMETERS */
+/*===================================================*/
+
+/*-----------------------------------------------*/
+/* VIDEO FORMAT DEFINITIONS */
+/*-----------------------------------------------*/
+
+#define DF_VIDFMT_UYVY 0x0000
+#define DF_VIDFMT_Y2YU 0x0001
+#define DF_VIDFMT_YUYV 0x0002
+#define DF_VIDFMT_YVYU 0x0003
+#define DF_VIDFMT_Y0Y1Y2Y3 0x0004
+#define DF_VIDFMT_Y3Y2Y1Y0 0x0005
+#define DF_VIDFMT_Y1Y0Y3Y2 0x0006
+#define DF_VIDFMT_Y1Y2Y3Y0 0x0007
+#define DF_VIDFMT_RGB 0x0008
+#define DF_VIDFMT_P2M_P2L_P1M_P1L 0x0009
+#define DF_VIDFMT_P1M_P1L_P2M_P2L 0x000A
+#define DF_VIDFMT_P1M_P2L_P2M_P1L 0x000B
+
+/*-----------------------------------------------*/
+/* CRT ENABLE STATES */
+/*-----------------------------------------------*/
+
+#define DF_CRT_DISABLE 0x0000
+#define DF_CRT_ENABLE 0x0001
+#define DF_CRT_STANDBY 0x0002
+#define DF_CRT_SUSPEND 0x0003
+
+/*-----------------------------------------------*/
+/* VIDEO SCALING FLAGS */
+/*-----------------------------------------------*/
+
+#define DF_SCALEFLAG_CHANGEX 0x0001
+#define DF_SCALEFLAG_CHANGEY 0x0002
+
+/*-----------------------------------------------*/
+/* DISPLAY FILTER COLOR SPACES */
+/*-----------------------------------------------*/
+
+#define DF_OUTPUT_RGB 0x0001
+#define DF_OUTPUT_ARGB 0x0002
+#define DF_OUTPUT_SDTV 0x0003
+#define DF_OUTPUT_HDTV 0x0004
+
+/*-----------------------------------------------*/
+/* DISPLAY FILTER OUTPUT PATHS */
+/*-----------------------------------------------*/
+
+#define DF_DISPLAY_CRT 0x0001
+#define DF_DISPLAY_FP 0x0002
+#define DF_DISPLAY_CRT_FP 0x0003
+#define DF_DISPLAY_VOP 0x0004
+#define DF_DISPLAY_DRGB 0x0005
+#define DF_DISPLAY_CRT_DRGB 0x0006
+
+/*-----------------------------------------------*/
+/* WINDOWED CRC DATA SOURCES */
+/*-----------------------------------------------*/
+
+#define DF_CRC_SOURCE_GFX_DATA 0x0000
+#define DF_CRC_SOURCE_CRT_RGB 0x0001
+#define DF_CRC_SOURCE_FP_DATA 0x0002
+
+/*-----------------------------------------------*/
+/* VIDEO ENABLE FLAGS */
+/*-----------------------------------------------*/
+
+#define DF_ENABLEFLAG_NOCOLORKEY 0x0001
+
+/*-----------------------------------------------*/
+/* USER STRUCTURE FOR CONFIGURING A VIDEO SOURCE */
+/*-----------------------------------------------*/
+
+#define DF_SOURCEFLAG_HDTVSOURCE 0x0001
+#define DF_SOURCEFLAG_IMPLICITSCALING 0x0002
+
+typedef struct tagVideoSourceInfo
+{
+ unsigned long video_format;
+ unsigned long y_offset;
+ unsigned long u_offset;
+ unsigned long v_offset;
+ unsigned long y_pitch;
+ unsigned long uv_pitch;
+ unsigned long width;
+ unsigned long height;
+ unsigned long flags;
+
+} DF_VIDEO_SOURCE_PARAMS;
+
+/*---------------------------------------------------*/
+/* USER STRUCTURE FOR CONFIGURING THE VIDEO POSITION */
+/*---------------------------------------------------*/
+
+#define DF_POSFLAG_DIRECTCLIP 0x0001
+#define DF_POSFLAG_INCLUDEBORDER 0x0002
+
+typedef struct tagVideoPosition
+{
+ long x;
+ long y;
+ unsigned long width;
+ unsigned long height;
+ unsigned long left_clip;
+ unsigned long dst_clip;
+ unsigned long flags;
+
+} DF_VIDEO_POSITION;
+
+/*-------------------------------------------------*/
+/* USER STRUCTURE FOR CONFIGURING THE VIDEO CURSOR */
+/*-------------------------------------------------*/
+
+typedef struct tagVideoCursorInfo
+{
+ unsigned long key;
+ unsigned long mask;
+ unsigned long color1;
+ unsigned long color2;
+ unsigned long select_color2;
+ unsigned long flags;
+
+} DF_VIDEO_CURSOR_PARAMS;
+
+/*-------------------------------------------------*/
+/* USER STRUCTURE FOR CONFIGURING AN ALPHA REGION */
+/*-------------------------------------------------*/
+
+#define DF_ALPHAFLAG_COLORENABLED 0x0001
+#define DF_ALPHAFLAG_PERPIXELENABLED 0x0002
+
+typedef struct tagAlphaRegionInfo
+{
+ unsigned long x;
+ unsigned long y;
+ unsigned long width;
+ unsigned long height;
+ unsigned long alpha_value;
+ unsigned long priority;
+ unsigned long color;
+ unsigned long flags;
+ long delta;
+
+} DF_ALPHA_REGION_PARAMS;
+
+/*-------------------------------------------------*/
+/* USER STRUCTURE FOR SAVING/RESTORING DF DATA */
+/*-------------------------------------------------*/
+
+typedef struct tagDFSaveRestore
+{
+ unsigned long vcfg;
+ unsigned long dcfg;
+ unsigned long video_x;
+ unsigned long video_y;
+ unsigned long video_scaler;
+ unsigned long video_color_key;
+ unsigned long video_color_mask;
+ unsigned long sat_limit;
+ unsigned long vid_misc;
+ unsigned long video_yscale;
+ unsigned long video_xscale;
+ unsigned long vid_alpha_control;
+ unsigned long cursor_key;
+ unsigned long cursor_mask;
+ unsigned long cursor_color1;
+ unsigned long cursor_color2;
+ unsigned long alpha_xpos1;
+ unsigned long alpha_ypos1;
+ unsigned long alpha_color1;
+ unsigned long alpha_control1;
+ unsigned long alpha_xpos2;
+ unsigned long alpha_ypos2;
+ unsigned long alpha_color2;
+ unsigned long alpha_control2;
+ unsigned long alpha_xpos3;
+ unsigned long alpha_ypos3;
+ unsigned long alpha_color3;
+ unsigned long alpha_control3;
+ unsigned long vid_request;
+ unsigned long vid_ypos_even;
+ unsigned long alpha_ypos_even1;
+ unsigned long alpha_ypos_even2;
+ unsigned long alpha_ypos_even3;
+ unsigned long panel_tim1;
+ unsigned long panel_tim2;
+ unsigned long panel_pm;
+ unsigned long panel_dither;
+
+ unsigned long palette[256];
+ unsigned long coefficients[512];
+
+ /* DF MSRS */
+
+ Q_WORD msr_cap;
+ Q_WORD msr_config;
+ Q_WORD msr_smi;
+ Q_WORD msr_error;
+ Q_WORD msr_pm;
+ Q_WORD msr_diag;
+ Q_WORD msr_df_diag;
+ Q_WORD msr_pad_sel;
+
+} DF_SAVE_RESTORE;
+
+/*-----------------------------------------------*/
+/* DF CRC SOURCES */
+/*-----------------------------------------------*/
+
+#define DF_CRC_SOURCE_ODD_FIELD 0x00000100
+#define DF_CRC_SOURCE_EVEN_FIELD 0x00001000
+#define DF_CRC_SOURCE_EVEN 0x00001000
+
+/*===================================================*/
+/* VIP USER PARAMETER DEFINITIONS */
+/*===================================================*/
+
+#define VIP_MODEFLAG_VSYNCACTIVEHIGH 0x00000001
+#define VIP_MODEFLAG_HSYNCACTIVEHIGH 0x00000002
+
+/*---------------------------------------------*/
+/* USER STRUCTURE FOR CONFIGURING 601 SETTINGS */
+/*---------------------------------------------*/
+
+typedef struct _TAG_VIP601PARAMS
+{
+ unsigned long flags;
+ unsigned long horz_start;
+ unsigned long width;
+ unsigned long vert_start_even;
+ unsigned long even_height;
+ unsigned long vert_start_odd;
+ unsigned long odd_height;
+ unsigned long vbi_start;
+ unsigned long vbi_height;
+ unsigned long odd_detect_start;
+ unsigned long odd_detect_end;
+
+} VIP_601PARAMS;
+
+/*-------------------------------------------*/
+/* USER STRUCTURE FOR CONFIGURING A VIP MODE */
+/*-------------------------------------------*/
+
+/* VIP MODE FLAGS */
+
+#define VIP_MODEFLAG_PLANARCAPTURE 0x00000001
+#define VIP_MODEFLAG_INVERTPOLARITY 0x00000002
+#define VIP_MODEFLAG_PROGRESSIVE 0x00000004
+#define VIP_MODEFLAG_DISABLEZERODETECT 0x00000008
+#define VIP_MODEFLAG_ENABLEREPEATFLAG 0x00000010
+#define VIP_MODEFLAG_10BITANCILLARY 0x00000020
+#define VIP_MODEFLAG_TOGGLEEACHFIELD 0x00000040
+#define VIP_MODEFLAG_INVERTTASKPOLARITY 0x00000080
+#define VIP_MODEFLAG_FLIPMESSAGEWHENFULL 0x00000100
+
+/* VIP CAPTURE ENABLE FLAGS */
+
+#define VIP_ENABLE_TASKA 0x00000100
+#define VIP_ENABLE_TASKA_VBI 0x00000200
+#define VIP_ENABLE_TASKB 0x00000400
+#define VIP_ENABLE_TASKB_VBI 0x00000800
+#define VIP_ENABLE_ANCILLARY 0x00001000
+#define VIP_ENABLE_ALL 0x00001F00
+
+/* VIP CAPTURE MODE FLAGS */
+
+#define VIP_MODE_IDLE 0x00000000
+#define VIP_MODE_VIP2_8BIT 0x00000002
+#define VIP_MODE_VIP2_16BIT 0x00000004
+#define VIP_MODE_VIP1_8BIT 0x00000006
+#define VIP_MODE_MSG 0x00000008
+#define VIP_MODE_DATA 0x0000000A
+#define VIP_MODE_8BIT601 0x0000000C
+#define VIP_MODE_16BIT601 0x0000000E
+
+/* 4:2:0 PLANAR CAPTURE METHODS */
+
+#define VIP_420CAPTURE_EVERYLINE 0x00000001
+#define VIP_420CAPTURE_ALTERNATINGLINES 0x00000002
+#define VIP_420CAPTURE_ALTERNATINGFIELDS 0x00000003
+
+typedef struct _TAG_SETMODEBUFFER
+{
+ unsigned long flags;
+ unsigned long stream_enables;
+ unsigned long operating_mode;
+ unsigned long planar_capture;
+ VIP_601PARAMS vip601_settings;
+
+} VIPSETMODEBUFFER;
+
+/*-----------------------------------------------*/
+/* USER STRUCTURE FOR CONFIGURING VG/VIP GENLOCK */
+/*-----------------------------------------------*/
+
+/* LOSS OF VIDEO DETECTION FLAGS */
+
+#define VIP_VDE_RUNAWAY_LINE 0x00800000
+#define VIP_VDE_VERTICAL_TIMING 0x00400000
+#define VIP_VDE_CLOCKS_PER_LINE 0x00200000
+#define VIP_VDE_LOST_CLOCK 0x00100000
+
+/* VIP VSYNC SELECT FOR THE VG */
+
+#define VIP_VGSYNC_NONE 0x00000000
+#define VIP_VGSYNC_START_FRAME 0x00000001
+#define VIP_VGSYNC_FALLING_EDGE_VBLANK 0x00000002
+#define VIP_VGSYNC_RISING_EDGE_VBLANK 0x00000003
+#define VIP_VGSYNC_FALLING_EDGE_FIELD 0x00000004
+#define VIP_VGSYNC_RISING_EDGE_FIELD 0x00000005
+#define VIP_VGSYNC_VIP_CURRENT_LINE 0x00000006
+#define VIP_VGSYNC_MSG_INT 0x00000007
+
+/* VIP FIELD SELECT FOR THE VG */
+
+#define VIP_VGFIELD_INPUT 0x00000000
+#define VIP_VGFIELD_INPUT_INV 0x00000008
+#define VIP_VGFIELD_ACTIVE_PAGE 0x00000010
+#define VIP_VGFIELD_ACTIVE_PAGE_IN 0x00000018
+
+/*--------------------------------------------------------*/
+/* USER STRUCTURE FOR CONFIGURING THE VG VSYNC GENLOCK */
+/*--------------------------------------------------------*/
+
+typedef struct _TAG_GENLOCKBUFFER
+{
+ unsigned long vip_signal_loss;
+ unsigned long vsync_to_vg;
+ unsigned long field_to_vg;
+ unsigned long genlock_skew;
+ int enable_timeout;
+
+} VIPGENLOCKBUFFER;
+
+/*------------------------------------------------------*/
+/* USER STRUCTURE FOR CONFIGURING VIP ANCILLARY CAPTURE */
+/*------------------------------------------------------*/
+
+typedef struct _TAG_ANCILLARYBUFFER
+{
+ unsigned long msg1_base;
+ unsigned long msg2_base;
+ unsigned long msg_size;
+
+} VIPANCILLARYBUFFER;
+
+/*----------------------------------------------------*/
+/* USER STRUCTURE FOR CONFIGURING VIP CAPTURE BUFFERS */
+/*----------------------------------------------------*/
+
+#define VIP_INPUTFLAG_VBI 0x00000001
+#define VIP_INPUTFLAG_INVERTPOLARITY 0x00000002
+#define VIP_INPUTFLAG_PLANAR 0x00000004
+
+#define VIP_MAX_BUFFERS 10
+
+#define VIP_BUFFER_TASK_A 0x0000
+#define VIP_BUFFER_TASK_B 0x0001
+#define VIP_BUFFER_MAX_TASKS 0x0002
+
+#define VIP_BUFFER_A 0x0000
+#define VIP_BUFFER_B 0x0001
+#define VIP_BUFFER_ANC 0x0002
+#define VIP_BUFFER_MSG 0x0003
+#define VIP_BUFFER_601 0x0004
+#define VIP_BUFFER_A_ODD 0x0005
+#define VIP_BUFFER_A_EVEN 0x0006
+#define VIP_BUFFER_B_ODD 0x0007
+#define VIP_BUFFER_B_EVEN 0x0008
+
+typedef struct _TAG_INPUTBUFFER_ADDR
+{
+ unsigned long even_base[VIP_MAX_BUFFERS];
+ unsigned long odd_base[VIP_MAX_BUFFERS];
+ unsigned long y_pitch;
+ unsigned long uv_pitch;
+ unsigned long odd_uoffset;
+ unsigned long odd_voffset;
+ unsigned long even_uoffset;
+ unsigned long even_voffset;
+ unsigned long vbi_even_base;
+ unsigned long vbi_odd_base;
+
+} VIPINPUTBUFFER_ADDR;
+
+typedef struct _TAG_SETINPUTBUFFER
+{
+ unsigned long flags;
+ VIPINPUTBUFFER_ADDR offsets[VIP_BUFFER_MAX_TASKS];
+ unsigned long current_buffer;
+
+ VIPANCILLARYBUFFER ancillaryData;
+
+} VIPINPUTBUFFER;
+
+/*------------------------------------------------------*/
+/* USER STRUCTURE FOR CONFIGURING VIP SUBWINDOW CAPTURE */
+/*------------------------------------------------------*/
+
+typedef struct _TAG_SUBWINDOWBUFFER
+{
+ int enable;
+ unsigned long start;
+ unsigned long stop;
+
+} VIPSUBWINDOWBUFFER;
+
+/*--------------------------------------------------------*/
+/* USER STRUCTURE FOR SAVING/RESTORING VIP REGISTERS */
+/*--------------------------------------------------------*/
+
+typedef struct _TAG_VIPSTATEBUFFER
+{
+ unsigned long control1;
+ unsigned long control2;
+ unsigned long vip_int;
+ unsigned long current_target;
+ unsigned long max_address;
+ unsigned long taska_evenbase;
+ unsigned long taska_oddbase;
+ unsigned long taska_vbi_evenbase;
+ unsigned long taska_vbi_oddbase;
+ unsigned long taska_data_pitch;
+ unsigned long control3;
+ unsigned long taska_v_oddoffset;
+ unsigned long taska_u_oddoffset;
+ unsigned long taskb_evenbase;
+ unsigned long taskb_oddbase;
+ unsigned long taskb_vbi_evenbase;
+ unsigned long taskb_vbi_oddbase;
+ unsigned long taskb_pitch;
+ unsigned long taskb_voffset;
+ unsigned long taskb_uoffset;
+ unsigned long msg1_base;
+ unsigned long msg2_base;
+ unsigned long msg_size;
+ unsigned long page_offset;
+ unsigned long vert_start_stop;
+ unsigned long vsync_err_count;
+ unsigned long taska_u_evenoffset;
+ unsigned long taska_v_evenoffset;
+
+ Q_WORD msr_config;
+ Q_WORD msr_smi;
+ Q_WORD msr_pm;
+ Q_WORD msr_diag;
+
+} VIPSTATEBUFFER;
+
+/*--------------------------------------------------------*/
+/* VIP_SET_CAPTURE_STATE USER PARAMETERS */
+/*--------------------------------------------------------*/
+
+#define VIP_STOPCAPTURE 0x0000
+#define VIP_STOPCAPTUREATLINEEND 0x0001
+#define VIP_STOPCAPTUREATFIELDEND 0x0002
+#define VIP_STOPCAPTUREATFRAMEEND 0x0003
+#define VIP_STARTCAPTUREATNEXTLINE 0x0004
+#define VIP_STARTCAPTUREATNEXTFIELD 0x0005
+#define VIP_STARTCAPTUREATNEXTFRAME 0x0006
+#define VIP_STARTCAPTURE 0x0007
+
+/*--------------------------------------------------------*/
+/* VIP_CONFIGURE_FIFO USER PARAMETERS */
+/*--------------------------------------------------------*/
+
+#define VIP_VIDEOTHRESHOLD 0x3000
+#define VIP_ANCILLARYTHRESHOLD 0x3001
+#define VIP_VIDEOFLUSH 0x3002
+#define VIP_ANCILLARYFLUSH 0x3003
+
+/*--------------------------------------------------------*/
+/* VIP_SET_INTERRUPT_ENABLE USER DEFINITIONS */
+/*--------------------------------------------------------*/
+
+#define VIP_INT_FIFO_ERROR 0x80000000
+#define VIP_INT_FIFO_WRAP 0x40000000
+#define VIP_INT_FIFO_OVERFLOW 0x20000000
+#define VIP_INT_FIFO_THRESHOLD 0x10000000
+#define VIP_INT_LONGLINE 0x08000000
+#define VIP_INT_VERTICAL_TIMING 0x04000000
+#define VIP_INT_ACTIVE_PIXELS 0x02000000
+#define VIP_INT_CLOCK_INPUT 0x01000000
+#define VIP_INT_ANC_CHECKSUM_PARITY 0x00800000
+#define VIP_INT_MSG_BUFFER_FULL 0x00400000
+#define VIP_INT_END_VBLANK 0x00200000
+#define VIP_INT_START_VBLANK 0x00100000
+#define VIP_INT_START_EVEN 0x00080000
+#define VIP_INT_START_ODD 0x00040000
+#define VIP_INT_LINE_MATCH_TARGET 0x00020000
+#define VIP_ALL_INTERRUPTS 0xFFFE0000
+
+/*--------------------------------------------------------*/
+/* VIP_GET_CURRENT_FIELD RETURN VALUES */
+/*--------------------------------------------------------*/
+
+#define VIP_ODD_FIELD 1
+#define VIP_EVEN_FIELD 0
+
+/*-------------------------------------------------*/
+/* USER STRUCTURE FOR QUERYING VIP CAPABILITIES */
+/*-------------------------------------------------*/
+
+typedef struct _TAG_CAPABILITIESBUFFER
+{
+ unsigned long revision_id;
+ unsigned long device_id;
+ unsigned long n_clock_domains;
+ unsigned long n_smi_registers;
+
+} VIPCAPABILITIESBUFFER;
+
+/*-------------------------------------------------*/
+/* USER STRUCTURE FOR CONFIGURING VIP POWER */
+/*-------------------------------------------------*/
+
+typedef struct _TAG_POWERBUFFER
+{
+ int glink_clock_mode;
+ int vip_clock_mode;
+
+} VIPPOWERBUFFER;
+
+/*-------------------------------------------------*/
+/* USER STRUCTURE FOR CONFIGURING VIP PRIORITIES */
+/*-------------------------------------------------*/
+
+typedef struct _TAG_PRIORITYBUFFER
+{
+ unsigned long secondary;
+ unsigned long primary;
+ unsigned long pid;
+
+} VIPPRIORITYBUFFER;
+
+/*--------------------------------------------------*/
+/* USER STRUCTURE FOR CONFIGURING VIP DEBUG OUTPUTS */
+/*--------------------------------------------------*/
+
+#define VIP_DIAG_UPPER_GLINK_MASTER 0x00010000
+#define VIP_DIAG_UPPER_GLINK_SLAVE 0x00020000
+#define VIP_DIAG_UPPER_GLINK_SLAVE_MMREG 0x00040000
+#define VIP_DIAG_UPPER_Y_BUFFER 0x00080000
+#define VIP_DIAG_UPPER_A_BUFFER 0x00100000
+#define VIP_DIAG_UPPER_FIFO_OUTPUT 0x00200000
+#define VIP_DIAG_UPPER_FIFO_INPUT 0x01000000
+#define VIP_DIAG_UPPER_FORMATTER 0x02000000
+#define VIP_DIAG_UPPER_INPUT_CONTROL 0x04000000
+
+#define VIP_DIAG_LOWER_GLINK_MASTER 0x00000001
+#define VIP_DIAG_LOWER_GLINK_SLAVE 0x00000002
+#define VIP_DIAG_LOWER_GLINK_SLAVE_MMREG 0x00000004
+#define VIP_DIAG_LOWER_Y_BUFFER 0x00000008
+#define VIP_DIAG_LOWER_A_BUFFER 0x00000010
+#define VIP_DIAG_LOWER_FIFO_OUTPUT 0x00000020
+#define VIP_DIAG_LOWER_FIFO_INPUT 0x00000100
+#define VIP_DIAG_LOWER_FORMATTER 0x00000200
+#define VIP_DIAG_LOWER_INPUT_CONTROL 0x00000400
+
+typedef struct _TAG_DEBUGBUFFER
+{
+ unsigned long bist;
+ unsigned long enable_upper;
+ unsigned long select_upper;
+ unsigned long enable_lower;
+ unsigned long select_lower;
+
+} VIPDEBUGBUFFER;
+
+
+/*===================================================*/
+/* VOP USER PARAMETER DEFINITIONS */
+/*===================================================*/
+
+/*------------------------------------------------------*/
+/* USER STRUCTURE FOR CONFIGURING VBI CAPTURE */
+/*------------------------------------------------------*/
+
+typedef struct _TAG_VBIWINDOWBUFFER
+{
+ long horz_start;
+ unsigned long vbi_width;
+ unsigned long odd_line_capture_mask;
+ unsigned long even_line_capture_mask;
+ unsigned long odd_line_offset;
+ unsigned long even_line_offset;
+ unsigned long even_address_offset;
+ unsigned long odd_address_offset;
+ unsigned long data_size;
+ unsigned long data_pitch;
+ int enable_upscale;
+ int horz_from_hsync;
+
+} VOPVBIWINDOWBUFFER;
+
+/*------------------------------------------------------*/
+/* USER STRUCTURE FOR CONFIGURING 601 FOR VOP */
+/*------------------------------------------------------*/
+
+#define VOP_601_INVERT_DISPE 0x00080000
+#define VOP_601_INVERT_VSYNC 0x00040000
+#define VOP_601_INVERT_HSYNC 0x00020000
+
+#define VOP_VSYNC_EARLIER_BY4 0x00000000
+#define VOP_VSYNC_EARLIER_BY2 0x00004000
+#define VOP_VSYNC_NOSHIFT 0x00008000
+#define VOP_VSYNC_LATER_BY_X 0x0000C000
+
+#define VOP_601_YUV_8BIT 0x00000000
+#define VOP_601_YUV_16BIT 0x00000001
+#define VOP_601_RGB_8_8_8 0x00000002
+#define VOP_601_YUV_4_4_4 0x00000003
+
+typedef struct _TAG_VOP601
+{
+ unsigned long flags;
+ unsigned long vsync_shift;
+ unsigned long vsync_shift_count;
+ unsigned long output_mode;
+
+} VOP_601DATA;
+
+/*------------------------------------------------------*/
+/* USER STRUCTURE FOR CONFIGURING VOP OUTPUT */
+/*------------------------------------------------------*/
+
+/* VOP FLAGS */
+
+#define VOP_FLAG_SINGLECHIPCOMPAT 0x00000001
+#define VOP_FLAG_EXTENDEDSAV 0x00000002
+#define VOP_FLAG_VBI 0x00000008
+#define VOP_FLAG_TASK 0x00000010
+#define VOP_FLAG_SWAP_UV 0x00000020
+#define VOP_FLAG_SWAP_VBI 0x00000040
+
+/* 4:4:2 TO 4:2:2 DECIMATION */
+
+#define VOP_422MODE_COSITED 0x00000000
+#define VOP_422MODE_INTERSPERSED 0x00000010
+#define VOP_422MODE_ALTERNATING 0x00000020
+
+/* VOP OPERATING MODES */
+
+#define VOP_MODE_DISABLED 0x00000000
+#define VOP_MODE_VIP11 0x00000001
+#define VOP_MODE_CCIR656 0x00000002
+#define VOP_MODE_VIP20_8BIT 0x00000003
+#define VOP_MODE_VIP20_16BIT 0x00000004
+#define VOP_MODE_601 0x00000005
+
+/* VSYNC OUT SELECT FLAGS */
+
+#define VOP_MB_SYNCSEL_DISABLED 0x00000000
+#define VOP_MB_SYNCSEL_VG 0x00000020
+#define VOP_MB_SYNCSEL_VG_INV 0x00000040
+#define VOP_MB_SYNCSEL_STATREG17 0x00000060
+#define VOP_MB_SYNCSEL_STATREG17_INV 0x00000080
+
+typedef struct _TAG_VOPMODECONFIGURATIONBUFFER
+{
+ unsigned long flags;
+ unsigned long mode;
+ unsigned long conversion_mode;
+ unsigned long vsync_out;
+ VOP_601DATA vop601;
+
+} VOPCONFIGURATIONBUFFER;
+
+/*--------------------------------------------------------*/
+/* USER STRUCTURE FOR SAVING/RESTORING VOP REGISTERS */
+/*--------------------------------------------------------*/
+
+typedef struct _TAG_VOPSTATEBUFFER
+{
+ unsigned long config;
+} VOPSTATEBUFFER;
+
+#endif
diff -Nru kernel-2.6.18geode-hurricane.orig/lib/cimarron/cim/cim_regs.h kernel-2.6.18geode-hurricane/lib/cimarron/cim/cim_regs.h
--- kernel-2.6.18geode-hurricane.orig/lib/cimarron/cim/cim_regs.h 1970-01-01 01:00:00.000000000 +0100
+++ kernel-2.6.18geode-hurricane/lib/cimarron/cim/cim_regs.h 2006-12-01 13:21:21.000000000 +0100
@@ -0,0 +1,1233 @@
+ /*
+ *
+ * Copyright (C) 2005 Advanced Micro Devices, Inc. All Rights Reserved.
+ *
+ *
+ *
+ *
+ *
+ *
+ * Cimarron register definitions
+ *
+ *
+ */
+
+#ifndef _cim_regs_h
+#define _cim_regs_h
+
+/*----------------------------------------------------------------*/
+/* GRAPHICS PROCESSOR DEFINITIONS */
+/*----------------------------------------------------------------*/
+
+/*----------------------------*/
+/* COMMAND BUFFER DEFINITIONS */
+/*----------------------------*/
+
+#define GP3_BLT_COMMAND_SIZE 68 /* 18 DWORDS */
+#define GP3_VECTOR_COMMAND_SIZE 56 /* 14 DWORDS */
+#define GP3_4BPP_LUT_COMMAND_SIZE 76 /* 16 DWORDS + 3 CMD DWORDS */
+#define GP3_8BPP_LUT_COMMAND_SIZE 1036 /* 256 DWORDS + 3 CMD DWORDS */
+#define GP3_VECTOR_PATTERN_COMMAND_SIZE 20 /* 2 DWORDS + 3 CMD DWORDS */
+#define GP3_MAX_COMMAND_SIZE 9000 /* 8K + WORKAROUND SPACE */
+#define GP3_SCRATCH_BUFFER_SIZE 0x100000 /* 1MB SCRATCH BUFFER */
+#define GP3_BLT_1PASS_SIZE 0xC7F8 /* (50K - 8) is largest 1-Pass load size */
+
+/*-------------------------------------*/
+/* BLT COMMAND BUFFER REGISTER OFFSETS */
+/*-------------------------------------*/
+
+#define GP3_BLT_CMD_HEADER 0x00000000
+#define GP3_BLT_RASTER_MODE 0x00000004
+#define GP3_BLT_DST_OFFSET 0x00000008
+#define GP3_BLT_SRC_OFFSET 0x0000000C
+#define GP3_BLT_STRIDE 0x00000010
+#define GP3_BLT_WID_HEIGHT 0x00000014
+#define GP3_BLT_SRC_COLOR_FG 0x00000018
+#define GP3_BLT_SRC_COLOR_BG 0x0000001C
+#define GP3_BLT_PAT_COLOR_0 0x00000020
+#define GP3_BLT_PAT_COLOR_1 0x00000024
+#define GP3_BLT_PAT_DATA_0 0x00000028
+#define GP3_BLT_PAT_DATA_1 0x0000002C
+#define GP3_BLT_CH3_OFFSET 0x00000030
+#define GP3_BLT_CH3_MODE_STR 0x00000034
+#define GP3_BLT_CH3_WIDHI 0x00000038
+#define GP3_BLT_BASE_OFFSET 0x0000003C
+#define GP3_BLT_MODE 0x00000040
+
+/*-----------------------------------------------------------------*/
+/* VECTOR COMMAND BUFFER REGISTER OFFSETS */
+/* Some of these are identical to the BLT registers (and we will */
+/* be assumed to be such in the Cimarron code, but they are listed */
+/* here for clarity and for future changes. */
+/*-----------------------------------------------------------------*/
+
+#define GP3_VEC_CMD_HEADER 0x00000000
+#define GP3_VECTOR_RASTER_MODE 0x00000004
+#define GP3_VECTOR_DST_OFFSET 0x00000008
+#define GP3_VECTOR_VEC_ERR 0x0000000C
+#define GP3_VECTOR_STRIDE 0x00000010
+#define GP3_VECTOR_VEC_LEN 0x00000014
+#define GP3_VECTOR_SRC_COLOR_FG 0x00000018
+#define GP3_VECTOR_PAT_COLOR_0 0x0000001C
+#define GP3_VECTOR_PAT_COLOR_1 0x00000020
+#define GP3_VECTOR_PAT_DATA_0 0x00000024
+#define GP3_VECTOR_PAT_DATA_1 0x00000028
+#define GP3_VECTOR_CH3_MODE_STR 0x0000002C
+#define GP3_VECTOR_BASE_OFFSET 0x00000030
+#define GP3_VECTOR_MODE 0x00000034
+
+/*---------------------------------------------------*/
+/* GP REGISTER DEFINITIONS */
+/* Addresses for writing or reading directly to/from */
+/* the graphics processor. */
+/*---------------------------------------------------*/
+
+#define GP3_DST_OFFSET 0x00000000
+#define GP3_SRC_OFFSET 0x00000004
+#define GP3_VEC_ERR 0x00000004
+#define GP3_STRIDE 0x00000008
+#define GP3_WID_HEIGHT 0x0000000C
+#define GP3_VEC_LEN 0x0000000C
+#define GP3_SRC_COLOR_FG 0x00000010
+#define GP3_SRC_COLOR_BG 0x00000014
+#define GP3_PAT_COLOR_0 0x00000018
+#define GP3_PAT_COLOR_1 0x0000001C
+#define GP3_PAT_COLOR_2 0x00000020
+#define GP3_PAT_COLOR_3 0x00000024
+#define GP3_PAT_COLOR_4 0x00000028
+#define GP3_PAT_COLOR_5 0x0000002C
+#define GP3_PAT_DATA_0 0x00000030
+#define GP3_PAT_DATA_1 0x00000034
+#define GP3_RASTER_MODE 0x00000038
+#define GP3_VEC_MODE 0x0000003C
+#define GP3_BLT_MODE 0x00000040
+#define GP3_BLT_STATUS 0x00000044
+#define GP3_HST_SRC 0x00000048
+#define GP3_BASE_OFFSET 0x0000004C
+#define GP3_CMD_TOP 0x00000050
+#define GP3_CMD_BOT 0x00000054
+#define GP3_CMD_READ 0x00000058
+#define GP3_CMD_WRITE 0x0000005C
+#define GP3_CH3_OFFSET 0x00000060
+#define GP3_CH3_MODE_STR 0x00000064
+#define GP3_CH3_WIDHI 0x00000068
+#define GP3_CH3_HST_SRC 0x0000006C
+#define GP3_LUT_ADDRESS 0x00000070
+#define GP3_LUT_DATA 0x00000074
+#define GP3_INT_CTL 0x00000078
+#define GP3_HST_SRC_RANGE 0x00000100
+
+/*------------------------*/
+/* REGISTER BIT FIELDS */
+/*------------------------*/
+
+/* GP3_BLT_CMD_HEADER BIT DEFINITIONS */
+
+#define GP3_BLT_HDR_WRAP 0x80000000
+#define GP3_BLT_HDR_TYPE 0x00000000
+#define GP3_BLT_HDR_HAZARD_ENABLE 0x10000000
+#define GP3_BLT_HDR_RASTER_ENABLE 0x00000001
+#define GP3_BLT_HDR_DST_OFF_ENABLE 0x00000002
+#define GP3_BLT_HDR_SRC_OFF_ENABLE 0x00000004
+#define GP3_BLT_HDR_STRIDE_ENABLE 0x00000008
+#define GP3_BLT_HDR_WIDHI_ENABLE 0x00000010
+#define GP3_BLT_HDR_SRC_FG_ENABLE 0x00000020
+#define GP3_BLT_HDR_SRC_BG_ENABLE 0x00000040
+#define GP3_BLT_HDR_PAT_CLR0_ENABLE 0x00000080
+#define GP3_BLT_HDR_PAT_CLR1_ENABLE 0x00000100
+#define GP3_BLT_HDR_PAT_DATA0_ENABLE 0x00000200
+#define GP3_BLT_HDR_PAT_DATA1_ENABLE 0x00000400
+#define GP3_BLT_HDR_CH3_OFF_ENABLE 0x00000800
+#define GP3_BLT_HDR_CH3_STR_ENABLE 0x00001000
+#define GP3_BLT_HDR_CH3_WIDHI_ENABLE 0x00002000
+#define GP3_BLT_HDR_BASE_OFFSET_ENABLE 0x00004000
+#define GP3_BLT_HDR_BLT_MODE_ENABLE 0x00008000
+
+/* GP3_VEC_CMD_HEADER BIT DEFINITIONS */
+
+#define GP3_VEC_HDR_WRAP 0x80000000
+#define GP3_VEC_HDR_TYPE 0x20000000
+#define GP3_VEC_HDR_HAZARD_ENABLE 0x10000000
+#define GP3_VEC_HDR_RASTER_ENABLE 0x00000001
+#define GP3_VEC_HDR_DST_OFF_ENABLE 0x00000002
+#define GP3_VEC_HDR_VEC_ERR_ENABLE 0x00000004
+#define GP3_VEC_HDR_STRIDE_ENABLE 0x00000008
+#define GP3_VEC_HDR_VEC_LEN_ENABLE 0x00000010
+#define GP3_VEC_HDR_SRC_FG_ENABLE 0x00000020
+#define GP3_VEC_HDR_PAT_CLR0_ENABLE 0x00000040
+#define GP3_VEC_HDR_PAT_CLR1_ENABLE 0x00000080
+#define GP3_VEC_HDR_PAT_DATA0_ENABLE 0x00000100
+#define GP3_VEC_HDR_PAT_DATA1_ENABLE 0x00000200
+#define GP3_VEC_HDR_CH3_STR_ENABLE 0x00000400
+#define GP3_VEC_HDR_BASE_OFFSET_ENABLE 0x00000800
+#define GP3_VEC_HDR_VEC_MODE_ENABLE 0x00001000
+
+/* GP3_RASTER_MODE BIT DEFINITIONS */
+
+#define GP3_RM_BPPFMT_332 0x00000000 /* 8 BPP, palettized */
+#define GP3_RM_BPPFMT_4444 0x40000000 /* 16 BPP, 4:4:4:4 */
+#define GP3_RM_BPPFMT_1555 0x50000000 /* 16 BPP, 1:5:5:5 */
+#define GP3_RM_BPPFMT_565 0x60000000 /* 16 BPP, 5:6:5 */
+#define GP3_RM_BPPFMT_8888 0x80000000 /* 32 BPP, 8:8:8:8 */
+#define GP3_RM_ALPHA_ALL 0x00C00000 /* Alpha enable */
+#define GP3_RM_ALPHA_TO_RGB 0x00400000 /* Alpha applies to RGB */
+#define GP3_RM_ALPHA_TO_ALPHA 0x00800000 /* Alpha applies to alpha */
+#define GP3_RM_ALPHA_OP_MASK 0x00300000 /* Alpha operation */
+#define GP3_RM_ALPHA_TIMES_A 0x00000000 /* Alpha * A */
+#define GP3_RM_BETA_TIMES_B 0x00100000 /* (1-alpha) * B */
+#define GP3_RM_A_PLUS_BETA_B 0x00200000 /* A + (1-alpha) * B */
+#define GP3_RM_ALPHA_A_PLUS_BETA_B 0x00300000 /* alpha * A + (1 - alpha)B */
+#define GP3_RM_ALPHA_SELECT 0x000E0000 /* Alpha Select */
+#define GP3_RM_SELECT_ALPHA_A 0x00000000 /* Alpha from channel A */
+#define GP3_RM_SELECT_ALPHA_B 0x00020000 /* Alpha from channel B */
+#define GP3_RM_SELECT_ALPHA_R 0x00040000 /* Registered alpha */
+#define GP3_RM_SELECT_ALPHA_1 0x00060000 /* Constant 1 */
+#define GP3_RM_SELECT_ALPHA_CHAN_A 0x00080000 /* RGB Values from A */
+#define GP3_RM_SELECT_ALPHA_CHAN_B 0x000A0000 /* RGB Values from B */
+#define GP3_RM_SELECT_ALPHA_CHAN_3 0x000C0000 /* Alpha from channel 3 */
+#define GP3_RM_DEST_FROM_CHAN_A 0x00010000 /* Alpha channel select */
+#define GP3_RM_PATTERN_INVERT 0x00001000 /* Invert monochrome pat */
+#define GP3_RM_SOURCE_INVERT 0x00002000 /* Invert monochrome src */
+#define GP3_RM_PAT_FLAGS 0x00000700 /* pattern related bits */
+#define GP3_RM_PAT_MONO 0x00000100 /* monochrome pattern */
+#define GP3_RM_PAT_COLOR 0x00000200 /* color pattern */
+#define GP3_RM_PAT_TRANS 0x00000400 /* pattern transparency */
+#define GP3_RM_SRC_TRANS 0x00000800 /* source transparency */
+
+/* GP3_VECTOR_MODE REGISTER DESCRIPTIONS */
+
+#define GP3_VM_DST_REQ 0x00000008 /* dst data required */
+#define GP3_VM_THROTTLE 0x00000010 /* sync to VBLANK */
+
+/* GP3_BLT_MODE REGISTER DEFINITIONS */
+
+#define GP3_BM_SRC_FB 0x00000001 /* src = frame buffer */
+#define GP3_BM_SRC_HOST 0x00000002 /* src = host register */
+#define GP3_BM_DST_REQ 0x00000004 /* dst data required */
+#define GP3_BM_SRC_MONO 0x00000040 /* monochrome source data */
+#define GP3_BM_SRC_BP_MONO 0x00000080 /* Byte-packed monochrome */
+#define GP3_BM_NEG_YDIR 0x00000100 /* negative Y direction */
+#define GP3_BM_NEG_XDIR 0x00000200 /* negative X direction */
+#define GP3_BM_THROTTLE 0x00000400 /* sync to VBLANK */
+
+/* GP3_BLT_STATUS REGISTER DEFINITIONS */
+
+#define GP3_BS_BLT_BUSY 0x00000001 /* GP is not idle */
+#define GP3_BS_BLT_PENDING 0x00000004 /* second BLT is pending */
+#define GP3_BS_HALF_EMPTY 0x00000008 /* src FIFO half empty */
+#define GP3_BS_CB_EMPTY 0x00000010 /* Command buffer empty. */
+
+/* GP3_CH3_MODE_STR REGISTER DEFINITIONS */
+
+#define GP3_CH3_C3EN 0x80000000
+#define GP3_CH3_REPLACE_SOURCE 0x40000000
+#define GP3_CH3_NEG_XDIR 0x20000000
+#define GP3_CH3_NEG_YDIR 0x10000000
+#define GP3_CH3_SRC_FMT_MASK 0x0f000000
+#define GP3_CH3_SRC_3_3_2 0x00000000
+#define GP3_CH3_SRC_8BPP_INDEXED 0x01000000
+#define GP3_CH3_SRC_8BPP_ALPHA 0x02000000
+#define GP3_CH3_SRC_4_4_4_4 0x04000000
+#define GP3_CH3_SRC_1_5_5_5 0x05000000
+#define GP3_CH3_SRC_0_5_6_5 0x06000000
+#define GP3_CH3_SRC_Y_U_V 0x07000000
+#define GP3_CH3_SRC_8_8_8_8 0x08000000
+#define GP3_CH3_SRC_24BPP_PACKED 0x0B000000
+#define GP3_CH3_SRC_4BPP_INDEXED 0x0D000000
+#define GP3_CH3_SRC_4BPP_ALPHA 0x0E000000
+#define GP3_CH3_SRC_MASK 0x0F000000
+#define GP3_CH3_ROTATE_ENABLE 0x00800000
+#define GP3_CH3_BGR_ORDER 0x00400000
+#define GP3_CH3_COLOR_PAT_ENABLE 0x00200000
+#define GP3_CH3_PRESERVE_LUT 0x00100000
+#define GP3_CH3_PREFETCH_ENABLE 0x00080000
+#define GP3_CH3_HST_SRC_ENABLE 0x00040000
+#define GP3_CH3_STRIDE_MASK 0x0000FFFF
+
+/* DATA AND LUT LOAD BIT DEFINITIONS */
+
+#define GP3_LUT_HDR_WRAP 0x80000000
+#define GP3_LUT_HDR_TYPE 0x40000000
+#define GP3_LUT_HDR_DATA_ENABLE 0x00000003
+#define GP3_DATA_LOAD_HDR_WRAP 0x80000000
+#define GP3_DATA_LOAD_HDR_TYPE 0x60000000
+#define GP3_DATA_LOAD_HDR_ENABLE 0x00000001
+
+#define GP3_HOST_SOURCE_TYPE 0x00000000
+#define GP3_CH3_HOST_SOURCE_TYPE 0x20000000
+#define GP3_OLD_PATTERN_COLORS 0x40000000
+#define GP3_LUT_DATA_TYPE 0x60000000
+
+#define GP3_BASE_OFFSET_DSTMASK 0xFFC00000
+#define GP3_BASE_OFFSET_SRCMASK 0x003FF000
+#define GP3_BASE_OFFSET_CH3MASK 0x00000FFC
+
+/*----------------------------------------------------------------*/
+/* VIDEO GENERATOR DEFINITIONS */
+/*----------------------------------------------------------------*/
+
+#define DC3_UNLOCK 0x00000000 /* Unlock register */
+#define DC3_GENERAL_CFG 0x00000004 /* Config registers */
+#define DC3_DISPLAY_CFG 0x00000008
+#define DC3_ARB_CFG 0x0000000C
+
+#define DC3_FB_ST_OFFSET 0x00000010 /* Frame buffer start offset */
+#define DC3_CB_ST_OFFSET 0x00000014 /* Compression start offset */
+#define DC3_CURS_ST_OFFSET 0x00000018 /* Cursor buffer start offset */
+#define DC3_VID_Y_ST_OFFSET 0x00000020 /* Video Y Buffer start offset */
+#define DC3_VID_U_ST_OFFSET 0x00000024 /* Video U Buffer start offset */
+#define DC3_VID_V_ST_OFFSET 0x00000028 /* Video V Buffer start offset */
+#define DC3_DV_TOP 0x0000002C /* DV Ram Limit Register */
+#define DC3_LINE_SIZE 0x00000030 /* Video, CB, and FB line sizes */
+#define DC3_GFX_PITCH 0x00000034 /* FB and DB skip counts */
+#define DC3_VID_YUV_PITCH 0x00000038 /* Y, U and V buffer skip counts */
+
+#define DC3_H_ACTIVE_TIMING 0x00000040 /* Horizontal timings */
+#define DC3_H_BLANK_TIMING 0x00000044
+#define DC3_H_SYNC_TIMING 0x00000048
+#define DC3_V_ACTIVE_TIMING 0x00000050 /* Vertical Timings */
+#define DC3_V_BLANK_TIMING 0x00000054
+#define DC3_V_SYNC_TIMING 0x00000058
+#define DC3_FB_ACTIVE 0x0000005C
+
+#define DC3_CURSOR_X 0x00000060 /* Cursor X position */
+#define DC3_CURSOR_Y 0x00000064 /* Cursor Y Position */
+#define DC3_LINE_CNT_STATUS 0x0000006C
+
+#define DC3_PAL_ADDRESS 0x00000070 /* Palette Address */
+#define DC3_PAL_DATA 0x00000074 /* Palette Data */
+#define DC3_DFIFO_DIAG 0x00000078 /* Display FIFO diagnostic */
+#define DC3_CFIFO_DIAG 0x0000007C /* Compression FIFO diagnostic */
+
+#define DC3_VID_DS_DELTA 0x00000080 /* Vertical Downscaling fraction */
+
+#define DC3_PHY_MEM_OFFSET 0x00000084 /* VG Base Address Register */
+#define DC3_DV_CTL 0x00000088 /* Dirty-Valid Control Register */
+#define DC3_DV_ACC 0x0000008C /* Dirty-Valid RAM Access */
+
+#define DC3_GFX_SCALE 0x00000090 /* Graphics Scaling */
+#define DC3_IRQ_FILT_CTL 0x00000094 /* VBlank interrupt and filters */
+#define DC3_FILT_COEFF1 0x00000098
+#define DC3_FILT_COEFF2 0x0000009C
+
+#define DC3_VBI_EVEN_CTL 0x000000A0 /* VBI Data Buffer Controls */
+#define DC3_VBI_ODD_CTL 0x000000A4
+#define DC3_VBI_HOR 0x000000A8
+#define DC3_VBI_LN_ODD 0x000000AC
+#define DC3_VBI_LN_EVEN 0x000000B0
+#define DC3_VBI_PITCH 0x000000B4
+
+#define DC3_COLOR_KEY 0x000000B8 /* Graphics color key */
+#define DC3_COLOR_MASK 0x000000BC /* Graphics color key mask */
+#define DC3_CLR_KEY_X 0x000000C0
+#define DC3_CLR_KEY_Y 0x000000C4
+
+#define DC3_IRQ 0x000000C8
+#define DC3_GENLK_CTL 0x000000D4
+
+#define DC3_VID_EVEN_Y_ST_OFFSET 0x000000D8 /* Even field video buffers */
+#define DC3_VID_EVEN_U_ST_OFFSET 0x000000DC
+#define DC3_VID_EVEN_V_ST_OFFSET 0x000000E0
+
+#define DC3_V_ACTIVE_EVEN 0x000000E4 /* Even field timing registers */
+#define DC3_V_BLANK_EVEN 0x000000E8
+#define DC3_V_SYNC_EVEN 0x000000EC
+
+/* UNLOCK VALUE */
+
+#define DC3_UNLOCK_VALUE 0x00004758 /* used to unlock DC regs */
+
+/* VG GEODELINK DEVICE SMI MSR FIELDS */
+
+#define DC3_VG_BL_MASK 0x00000001
+#define DC3_MISC_MASK 0x00000002
+#define DC3_ISR0_MASK 0x00000004
+#define DC3_VGA_BL_MASK 0x00000008
+#define DC3_CRTCIO_MSK 0x00000010
+#define DC3_VG_BLANK_SMI 0x00000001
+#define DC3_MISC_SMI 0x00000002
+#define DC3_ISR0_SMI 0x00000004
+#define DC3_VGA_BLANK_SMI 0x00000008
+#define DC3_CRTCIO_SMI 0x00000010
+
+/* DC3_GENERAL_CFG BIT FIELDS */
+
+#define DC3_GCFG_DBUG 0x80000000
+#define DC3_GCFG_DBSL 0x40000000
+#define DC3_GCFG_CFRW 0x20000000
+#define DC3_GCFG_DIAG 0x10000000
+#define DC3_GCFG_CRC_MODE 0x08000000
+#define DC3_GCFG_SGFR 0x04000000
+#define DC3_GCFG_SGRE 0x02000000
+#define DC3_GCFG_SIGE 0x01000000
+#define DC3_GCFG_SIG_SEL 0x00800000
+#define DC3_GCFG_YUV_420 0x00100000
+#define DC3_GCFG_VDSE 0x00080000
+#define DC3_GCFG_VGAFT 0x00040000
+#define DC3_GCFG_FDTY 0x00020000
+#define DC3_GCFG_STFM 0x00010000
+#define DC3_GCFG_DFHPEL_MASK 0x0000F000
+#define DC3_GCFG_DFHPSL_MASK 0x00000F00
+#define DC3_GCFG_VGAE 0x00000080
+#define DC3_GCFG_DECE 0x00000040
+#define DC3_GCFG_CMPE 0x00000020
+#define DC3_GCFG_FILT_SIG_SEL 0x00000010
+#define DC3_GCFG_VIDE 0x00000008
+#define DC3_GCFG_CLR_CUR 0x00000004
+#define DC3_GCFG_CURE 0x00000002
+#define DC3_GCFG_DFLE 0x00000001
+
+/* DC3_DISPLAY_CFG BIT FIELDS */
+
+#define DC3_DCFG_VISL 0x08000000
+#define DC3_DCFG_FRLK 0x04000000
+#define DC3_DCFG_PALB 0x02000000
+#define DC3_DCFG_DCEN 0x01000000
+#define DC3_DCFG_VFHPEL_MASK 0x000F0000
+#define DC3_DCFG_VFHPSL_MASK 0x0000F000
+#define DC3_DCFG_16BPP_MODE_MASK 0x00000C00
+#define DC3_DCFG_16BPP 0x00000000
+#define DC3_DCFG_15BPP 0x00000400
+#define DC3_DCFG_12BPP 0x00000800
+#define DC3_DCFG_DISP_MODE_MASK 0x00000300
+#define DC3_DCFG_DISP_MODE_8BPP 0x00000000
+#define DC3_DCFG_DISP_MODE_16BPP 0x00000100
+#define DC3_DCFG_DISP_MODE_24BPP 0x00000200
+#define DC3_DCFG_DISP_MODE_32BPP 0x00000300
+#define DC3_DCFG_TRUP 0x00000040
+#define DC3_DCFG_VDEN 0x00000010
+#define DC3_DCFG_GDEN 0x00000008
+#define DC3_DCFG_TGEN 0x00000001
+
+/* DC3_ARB_CFG BIT FIELDS */
+
+#define DC3_ACFG_LB_LOAD_WM_EN 0x00100000
+#define DC3_ACFG_LB_LOAD_WM_MASK 0x000F0000
+#define DC3_ACFG_LPEN_END_COUNT_MASK 0x0000FE00
+#define DC3_ACFG_HPEN_SBINV 0x00000100
+#define DC3_ACFG_HPEN_FB_INV_HALFSB 0x00000080
+#define DC3_ACFG_HPEN_FB_INV_SBRD 0x00000040
+#define DC3_ACFG_HPEN_FB_INV 0x00000020
+#define DC3_ACFG_HPEN_1LB_INV 0x00000010
+#define DC3_ACFG_HPEN_2LB_INV 0x00000008
+#define DC3_ACFG_HPEN_3LB_INV 0x00000004
+#define DC3_ACFG_HPEN_LB_FILL 0x00000002
+#define DC3_ACFG_LPEN_VSYNC 0x00000001
+
+/* DC3_FB_ST_OFFSET BIT FIELDS */
+
+#define DC3_FB_ST_OFFSET_MASK 0x0FFFFFFF
+
+/* DC3_CB_ST_OFFSET BIT FIELDS */
+
+#define DC3_CB_ST_OFFSET_MASK 0x0FFFFFFF
+
+/* DC3_CURS_ST_OFFSET BIT FIELDS */
+
+#define DC3_CURS_ST_OFFSET_MASK 0x0FFFFFFF
+
+/* DC3_ICON_ST_OFFSET BIT FIELDS */
+
+#define DC3_ICON_ST_OFFSET_MASK 0x0FFFFFFF
+
+/* DC3_VID_Y_ST_OFFSET BIT FIELDS */
+
+#define DC3_VID_Y_ST_OFFSET_MASK 0x0FFFFFFF
+
+/* DC3_VID_U_ST_OFFSET BIT FIELDS */
+
+#define DC3_VID_U_ST_OFFSET_MASK 0x0FFFFFFF
+
+/* DC3_VID_V_ST_OFFSET BIT FIELDS */
+
+#define DC3_VID_V_ST_OFFSET_MASK 0x0FFFFFFF
+
+/* DC3_DV_TOP BIT FIELDS */
+
+#define DC3_DVTOP_ENABLE 0x00000001
+#define DC3_DVTOP_MAX_MASK 0x00FFFC00
+#define DC3_DVTOP_MAX_SHIFT 10
+
+/* DC3_LINE_SIZE BIT FIELDS */
+
+#define DC3_LINE_SIZE_VLS_MASK 0x3FF00000
+#define DC3_LINE_SIZE_CBLS_MASK 0x0007F000
+#define DC3_LINE_SIZE_FBLS_MASK 0x000003FF
+#define DC3_LINE_SIZE_CB_SHIFT 12
+#define DC3_LINE_SIZE_VB_SHIFT 20
+
+/* DC3_GFX_PITCH BIT FIELDS */
+
+#define DC3_GFX_PITCH_CBP_MASK 0xFFFF0000
+#define DC3_GFX_PITCH_FBP_MASK 0x0000FFFF
+
+/* DC3_VID_YUV_PITCH BIT FIELDS */
+
+#define DC3_YUV_PITCH_UVP_MASK 0xFFFF0000
+#define DC3_YUV_PITCH_YBP_MASK 0x0000FFFF
+
+/* DC3_H_ACTIVE_TIMING BIT FIELDS */
+
+#define DC3_HAT_HT_MASK 0x0FF80000
+#define DC3_HAT_HA_MASK 0x00000FF8
+
+/* DC3_H_BLANK_TIMING BIT FIELDS */
+
+#define DC3_HBT_HBE_MASK 0x0FF80000
+#define DC3_HBT_HBS_MASK 0x00000FF8
+
+/* DC3_H_SYNC_TIMING BIT FIELDS */
+
+#define DC3_HST_HSE_MASK 0x0FF80000
+#define DC3_HST_HSS_MASK 0x00000FF8
+
+/* DC3_V_ACTIVE_TIMING BIT FIELDS */
+
+#define DC3_VAT_VT_MASK 0x07FF0000
+#define DC3_VAT_VA_MASK 0x000007FF
+
+/* DC3_V_BLANK_TIMING BIT FIELDS */
+
+#define DC3_VBT_VBE_MASK 0x07FF0000
+#define DC3_VBT_VBS_MASK 0x000007FF
+
+/* DC3_V_SYNC_TIMING BIT FIELDS */
+
+#define DC3_VST_VSE_MASK 0x07FF0000
+#define DC3_VST_VSS_MASK 0x000007FF
+
+/* DC3_LINE_CNT_STATUS BIT FIELDS */
+
+#define DC3_LNCNT_DNA 0x80000000
+#define DC3_LNCNT_VNA 0x40000000
+#define DC3_LNCNT_VSA 0x20000000
+#define DC3_LNCNT_VINT 0x10000000
+#define DC3_LNCNT_FLIP 0x08000000
+#define DC3_LNCNT_V_LINE_CNT 0x07FF0000
+#define DC3_LNCNT_VFLIP 0x00008000
+#define DC3_LNCNT_SIGC 0x00004000
+#define DC3_LNCNT_EVEN_FIELD 0x00002000
+#define DC3_LNCNT_SS_LINE_CMP 0x000007FF
+
+/* DC3_VID_DS_DELTA BIT FIELDS */
+
+#define DC3_DS_DELTA_MASK 0xFFFC0000
+#define DC3_601_VSYNC_SHIFT_MASK 0x00000FFF
+#define DC3_601_VSYNC_SHIFT_ENABLE 0x00008000
+
+/* DC3_DV_CTL BIT DEFINITIONS */
+
+#define DC3_DV_LINE_SIZE_MASK 0x00000C00
+#define DC3_DV_LINE_SIZE_1024 0x00000000
+#define DC3_DV_LINE_SIZE_2048 0x00000400
+#define DC3_DV_LINE_SIZE_4096 0x00000800
+#define DC3_DV_LINE_SIZE_8192 0x00000C00
+
+/* DC3_IRQ_FILT_CTL DEFINITIONS */
+
+#define DC3_IRQFILT_LB_MASK 0x80000200
+#define DC3_IRQFILT_LB_COEFF 0x00000000
+#define DC3_IRQFILT_SCALER_FILTER 0x00000200
+#define DC3_IRQFILT_SYNCHRONIZER 0x80000000
+#define DC3_IRQFILT_FLICKER_FILTER 0x80000200
+#define DC3_IRQFILT_LB_SEL_MASK 0x60000000
+#define DC3_IRQFILT_INTL_ADDR 0x10000000
+#define DC3_IRQFILT_LINE_MASK 0x07FF0000
+#define DC3_IRQFILT_ALPHA_FILT_EN 0x00004000
+#define DC3_IRQFILT_GFX_FILT_EN 0x00001000
+#define DC3_IRQFILT_INTL_EN 0x00000800
+#define DC3_IRQFILT_H_FILT_SEL 0x00000400
+#define DC3_IRQFILT_LB_ADDR 0x00000100
+
+/* DC3_VBI_EVEN_CTL DEFINITIONS */
+
+#define DC3_VBI_EVEN_ENABLE_CRC (1L << 31)
+#define DC3_VBI_EVEN_CTL_ENABLE_16 (1L << 30)
+#define DC3_VBI_EVEN_CTL_UPSCALE (1L << 29)
+#define DC3_VBI_ENABLE (1L << 28)
+#define DC3_VBI_EVEN_CTL_OFFSET_MASK 0x0FFFFFFF
+
+/* DC3_VBI_ODD_CTL DEFINITIONS */
+
+#define DC3_VBI_ODD_CTL_OFFSET_MASK 0x0FFFFFFF
+
+/* DC3_VBI_HOR BIT DEFINITIONS */
+
+#define DC3_VBI_HOR_END_SHIFT 16
+#define DC3_VBI_HOR_END_MASK 0x0FFF0000
+#define DC3_VBI_HOR_START_MASK 0x00000FFF
+
+/* DC3_VBI_LN_ODD BIT DEFINITIONS */
+
+#define DC3_VBI_ODD_ENABLE_SHIFT 2
+#define DC3_VBI_ODD_ENABLE_MASK 0x01FFFFFC
+#define DC3_VBI_ODD_LINE_SHIFT 25
+#define DC3_VBI_ODD_LINE_MASK 0xFE000000
+
+/* DC3_VBI_LN_EVEN BIT DEFINITIONS */
+
+#define DC3_VBI_EVEN_ENABLE_SHIFT 2
+#define DC3_VBI_EVEN_ENABLE_MASK 0x01FFFFFC
+#define DC3_VBI_EVEN_LINE_SHIFT 25
+#define DC3_VBI_EVEN_LINE_MASK 0xFE000000
+
+/* DC3_COLOR_KEY DEFINITIONS */
+
+#define DC3_CLR_KEY_DATA_MASK 0x00FFFFFF
+#define DC3_CLR_KEY_ENABLE 0x01000000
+
+/* DC3_IRQ DEFINITIONS */
+
+#define DC3_IRQ_MASK 0x00000001
+#define DC3_VSYNC_IRQ_MASK 0x00000002
+#define DC3_IRQ_STATUS 0x00010000
+#define DC3_VSYNC_IRQ_STATUS 0x00020000
+
+/* DC3_GENLK_CTL DEFINITIONS */
+
+#define DC3_GC_FLICKER_FILTER_NONE 0x00000000
+#define DC3_GC_FLICKER_FILTER_1_16 0x10000000
+#define DC3_GC_FLICKER_FILTER_1_8 0x20000000
+#define DC3_GC_FLICKER_FILTER_1_4 0x40000000
+#define DC3_GC_FLICKER_FILTER_5_16 0x50000000
+#define DC3_GC_FLICKER_FILTER_MASK 0xF0000000
+#define DC3_GC_ALPHA_FLICK_ENABLE 0x02000000
+#define DC3_GC_FLICKER_FILTER_ENABLE 0x01000000
+#define DC3_GC_VIP_VID_OK 0x00800000
+#define DC3_GC_GENLK_ACTIVE 0x00400000
+#define DC3_GC_SKEW_WAIT 0x00200000
+#define DC3_GC_VSYNC_WAIT 0x00100000
+#define DC3_GC_GENLOCK_TO_ENABLE 0x00080000
+#define DC3_GC_GENLOCK_ENABLE 0x00040000
+#define DC3_GC_GENLOCK_SKEW_MASK 0x0003FFFF
+
+/* VGA DEFINITIONS */
+
+#define DC3_SEQUENCER_INDEX 0x03C4
+#define DC3_SEQUENCER_DATA 0x03C5
+#define DC3_SEQUENCER_RESET 0x00
+#define DC3_SEQUENCER_CLK_MODE 0x01
+
+#define DC3_RESET_VGA_DISP_ENABLE 0x03
+#define DC3_CLK_MODE_SCREEN_OFF 0x20
+
+/* DOT CLOCK FREQUENCY STRUCTURE */
+/* Note that m, n and p refer to the register m, n and p */
+/* and not the m, n and p from the PLL equation. The PLL */
+/* equation adds 1 to each value. */
+
+typedef struct tagPLLFrequency
+{
+ unsigned long pll_value;
+ unsigned long frequency;
+
+} PLL_FREQUENCY;
+
+/* VG MSRS */
+
+#define DC3_SPARE_MSR 0x2011
+#define DC3_RAM_CTL 0x2012
+
+/* DC3_SPARE_MSR DEFINITIONS */
+
+#define DC3_SPARE_DISABLE_CFIFO_HGO 0x00000800
+#define DC3_SPARE_VFIFO_ARB_SELECT 0x00000400
+#define DC3_SPARE_WM_LPEN_OVRD 0x00000200
+#define DC3_SPARE_LOAD_WM_LPEN_MASK 0x00000100
+#define DC3_SPARE_DISABLE_INIT_VID_PRI 0x00000080
+#define DC3_SPARE_DISABLE_VFIFO_WM 0x00000040
+#define DC3_SPARE_DISABLE_CWD_CHECK 0x00000020
+#define DC3_SPARE_PIX8_PAN_FIX 0x00000010
+#define DC3_SPARE_FIRST_REQ_MASK 0x00000002
+
+/* VG DIAG DEFINITIONS */
+
+#define DC3_MBD_DIAG_EN0 0x00008000
+#define DC3_MBD_DIAG_EN1 0x80000000
+#define DC3_DIAG_DOT_CRTC_DP 0x00000082
+#define DC3_DIAG_DOT_CRTC_DP_HIGH 0x00820000
+#define DC3_DIAG_EVEN_FIELD 0x00002000
+
+/*----------------------------------------------------------------*/
+/* DISPLAY FILTER DEFINITIONS */
+/*----------------------------------------------------------------*/
+
+#define DF_VIDEO_CONFIG 0x00000000
+#define DF_DISPLAY_CONFIG 0x00000008
+#define DF_VIDEO_X_POS 0x00000010
+#define DF_VIDEO_Y_POS 0x00000018
+#define DF_VIDEO_SCALER 0x00000020
+#define DF_VIDEO_COLOR_KEY 0x00000028
+#define DF_VIDEO_COLOR_MASK 0x00000030
+#define DF_PALETTE_ADDRESS 0x00000038
+#define DF_PALETTE_DATA 0x00000040
+#define DF_SATURATION_LIMIT 0x00000048
+#define DF_VID_MISC 0x00000050
+#define DF_VIDEO_YSCALE 0x00000060
+#define DF_VIDEO_XSCALE 0x00000068
+#define DF_VID_CRC 0x00000088
+#define DF_VID_CRC32 0x00000090
+#define DF_VID_ALPHA_CONTROL 0x00000098
+#define DF_CURSOR_COLOR_KEY 0x000000A0
+#define DF_CURSOR_COLOR_MASK 0x000000A8
+#define DF_CURSOR_COLOR_1 0x000000B0
+#define DF_CURSOR_COLOR_2 0x000000B8
+#define DF_ALPHA_XPOS_1 0x000000C0
+#define DF_ALPHA_YPOS_1 0x000000C8
+#define DF_ALPHA_COLOR_1 0x000000D0
+#define DF_ALPHA_CONTROL_1 0x000000D8
+#define DF_ALPHA_XPOS_2 0x000000E0
+#define DF_ALPHA_YPOS_2 0x000000E8
+#define DF_ALPHA_COLOR_2 0x000000F0
+#define DF_ALPHA_CONTROL_2 0x000000F8
+#define DF_ALPHA_XPOS_3 0x00000100
+#define DF_ALPHA_YPOS_3 0x00000108
+#define DF_ALPHA_COLOR_3 0x00000110
+#define DF_ALPHA_CONTROL_3 0x00000118
+#define DF_VIDEO_REQUEST 0x00000120
+#define DF_ALPHA_WATCH 0x00000128
+#define DF_VIDEO_TEST_MODE 0x00000130
+#define DF_VID_YPOS_EVEN 0x00000138
+#define DF_VID_ALPHA_Y_EVEN_1 0x00000140
+#define DF_VID_ALPHA_Y_EVEN_2 0x00000148
+#define DF_VID_ALPHA_Y_EVEN_3 0x00000150
+#define DF_VIDEO_PANEL_TIM1 0x00000400
+#define DF_VIDEO_PANEL_TIM2 0x00000408
+#define DF_POWER_MANAGEMENT 0x00000410
+#define DF_DITHER_CONTROL 0x00000418
+#define DF_DITHER_ACCESS 0x00000448
+#define DF_DITHER_DATA 0x00000450
+#define DF_PANEL_CRC 0x00000458
+#define DF_PANEL_CRC32 0x00000468
+#define DF_COEFFICIENT_BASE 0x00001000
+
+/* DF_VIDEO_CONFIG BIT DEFINITIONS */
+
+#define DF_VCFG_VID_EN 0x00000001
+#define DF_VCFG_VID_INP_FORMAT 0x0000000C
+#define DF_VCFG_SC_BYP 0x00000020
+#define DF_VCFG_LINE_SIZE_LOWER_MASK 0x0000FF00
+#define DF_VCFG_INIT_READ_MASK 0x01FF0000
+#define DF_VCFG_LINE_SIZE_BIT8 0x08000000
+#define DF_VCFG_LINE_SIZE_BIT9 0x04000000
+#define DF_VCFG_4_2_0_MODE 0x10000000
+#define DF_VCFG_UYVY_FORMAT 0x00000000
+#define DF_VCFG_Y2YU_FORMAT 0x00000004
+#define DF_VCFG_YUYV_FORMAT 0x00000008
+#define DF_VCFG_YVYU_FORMAT 0x0000000C
+
+/* DF_DISPLAY_CONFIG BIT DEFINITIONS */
+
+#define DF_DCFG_DIS_EN 0x00000001
+#define DF_DCFG_HSYNC_EN 0x00000002
+#define DF_DCFG_VSYNC_EN 0x00000004
+#define DF_DCFG_DAC_BL_EN 0x00000008
+#define DF_DCFG_CRT_HSYNC_POL 0x00000100
+#define DF_DCFG_CRT_VSYNC_POL 0x00000200
+#define DF_DCFG_CRT_SYNC_SKW_MASK 0x0001C000
+#define DF_DCFG_CRT_SYNC_SKW_INIT 0x00010000
+#define DF_DCFG_PWR_SEQ_DLY_MASK 0x000E0000
+#define DF_DCFG_PWR_SEQ_DLY_INIT 0x00080000
+#define DF_DCFG_VG_CK 0x00100000
+#define DF_DCFG_GV_PAL_BYP 0x00200000
+#define DF_DAC_VREF 0x04000000
+
+/* DF_VID_MISC BIT DEFINITIONS */
+
+#define DF_GAMMA_BYPASS_BOTH 0x00000001
+#define DF_DAC_POWER_DOWN 0x00000400
+#define DF_ANALOG_POWER_DOWN 0x00000800
+#define DF_USER_IMPLICIT_SCALING 0x00001000
+
+/* DF_VID_ALPHA_CONTROL DEFINITIONS */
+
+#define DF_HD_VIDEO 0x00000040
+#define DF_YUV_CSC_EN 0x00000080
+#define DF_NO_CK_OUTSIDE_ALPHA 0x00000100
+#define DF_HD_GRAPHICS 0x00000200
+#define DF_CSC_VIDEO_YUV_TO_RGB 0x00000400
+#define DF_CSC_GRAPHICS_RGB_TO_YUV 0x00000800
+#define DF_CSC_VOP_RGB_TO_YUV 0x00001000
+#define DF_VIDEO_INPUT_IS_RGB 0x00002000
+#define DF_VID_ALPHA_EN 0x00004000
+#define DF_ALPHA_DRGB 0x00008000
+
+/* VIDEO CURSOR COLOR KEY DEFINITIONS */
+
+#define DF_CURSOR_COLOR_KEY_ENABLE 0x20000000
+
+/* ALPHA COLOR BIT DEFINITION */
+
+#define DF_ALPHA_COLOR_ENABLE 0x01000000
+
+/* ALPHA CONTROL BIT DEFINITIONS */
+
+#define DF_ACTRL_WIN_ENABLE 0x00010000
+#define DF_ACTRL_LOAD_ALPHA 0x00020000
+#define DF_ACTRL_PERPIXEL_EN 0x00040000
+
+/* DF_VIDEO_SCALER DEFINITIONS */
+
+#define DF_SCALE_128_PHASES 0x00002000
+#define DF_SCALE_DOUBLE_H_DOWNSCALE 0x00004000
+
+/* DEFAULT PANEL TIMINGS DEFINITIONS */
+
+#define DF_DEFAULT_TFT_PMTIM1 0x00000000
+#define DF_DEFAULT_XVGA_PMTIM1 0x00000000
+#define DF_DEFAULT_TFT_PMTIM2 0x08C00000
+#define DF_DEFAULT_XVGA_PMTIM2 0x08C10000
+#define DF_DEFAULT_TFT_PAD_SEL_LOW 0xDFFFFFFF
+#define DF_DEFAULT_TFT_PAD_SEL_HIGH 0x0000003F
+#define DF_DEFAULT_XVGA_PAD_SEL_LOW 0x00000000
+#define DF_DEFAULT_XVGA_PAD_SEL_HIGH 0x00000000
+#define DF_DEFAULT_DITHCTL 0x00000070
+#define DF_DEFAULT_TV_PAD_SEL_HIGH 0x000000BF
+#define DF_DEFAULT_TV_PAD_SEL_LOW 0xDFFFFFFF
+#define DF_INVERT_VOP_CLOCK 0x00000080
+
+/* DF_VIDEO_PANEL_TIM2 DEFINITIONS */
+
+#define DF_PMTIM2_TFT_PASSHTHROUGH 0x40000000
+
+/* DF_POWER_MANAGEMENT DEFINITIONS */
+
+#define DF_PM_PANEL_ON 0x01000000
+#define DF_PM_INVERT_SHFCLK 0x00002000
+
+/* DISPLAY FILTER MSRS */
+
+#define DF_MBD_MSR_DIAG_DF 0x2010
+#define DF_MSR_PAD_SEL 0x2011
+#define DF_DIAG_32BIT_CRC 0x80000000
+
+#define DF_OUTPUT_CRT 0x00000000
+#define DF_OUTPUT_PANEL 0x00000008
+#define DF_OUTPUT_VOP 0x00000030
+#define DF_OUTPUT_DRGB 0x00000038
+#define DF_SIMULTANEOUS_CRT_FP 0x00008000
+#define DF_CONFIG_OUTPUT_MASK 0x00000038
+
+/*----------------------------------------------------------------*/
+/* MSR DEFINITIONS */
+/*----------------------------------------------------------------*/
+
+/*----------------------------*/
+/* STATIC GEODELINK ADRESSES */
+/*----------------------------*/
+
+#define MSR_ADDRESS_GLIU0 0x10000000
+#define MSR_ADDRESS_GLIU1 0x40000000
+#define MSR_ADDRESS_GLIU2 0x51010000
+#define MSR_ADDRESS_5535MPCI 0x51000000
+#define MSR_ADDRESS_VAIL 0x00000000
+
+/*----------------------------*/
+/* UNIVERSAL DEVICE MSRS */
+/*----------------------------*/
+
+#define MSR_GEODELINK_CAP 0x2000
+#define MSR_GEODELINK_CONFIG 0x2001
+#define MSR_GEODELINK_SMI 0x2002
+#define MSR_GEODELINK_ERROR 0x2003
+#define MSR_GEODELINK_PM 0x2004
+#define MSR_GEODELINK_DIAG 0x2005
+
+/*----------------------------*/
+/* DEVICE CLASS CODES */
+/*----------------------------*/
+
+#define MSR_CLASS_CODE_GLIU 0x01
+#define MSR_CLASS_CODE_GLCP 0x02
+#define MSR_CLASS_CODE_MPCI 0x05
+#define MSR_CLASS_CODE_MC 0x20
+#define MSR_CLASS_CODE_GP 0x3D
+#define MSR_CLASS_CODE_VG 0x3E
+#define MSR_CLASS_CODE_DF 0x3F
+#define MSR_CLASS_CODE_FG 0xF0
+#define MSR_CLASS_CODE_VAIL 0x86
+#define MSR_CLASS_CODE_USB 0x42
+#define MSR_CLASS_CODE_USB2 0x43
+#define MSR_CLASS_CODE_ATAC 0x47
+#define MSR_CLASS_CODE_MDD 0xDF
+#define MSR_CLASS_CODE_ACC 0x33
+#define MSR_CLASS_CODE_AES 0x30
+#define MSR_CLASS_CODE_VIP 0x3C
+#define MSR_CLASS_CODE_REFLECTIVE 0xFFF
+#define MSR_CLASS_CODE_UNPOPULATED 0x7FF
+
+/*----------------------------*/
+/* GLIU MSR DEFINITIONS */
+/*----------------------------*/
+
+#define MSR_GLIU_CAP 0x0086
+#define MSR_GLIU_WHOAMI 0x008B
+
+#define NUM_PORTS_MASK 0x00380000
+#define NUM_PORTS_SHIFT 19
+#define WHOAMI_MASK 0x07
+
+/*----------------------------*/
+/* GLCP MSR DEFINITIONS */
+/*----------------------------*/
+
+#define GLCP_CLKOFF 0x0010
+#define GLCP_CLKACTIVE 0x0011
+#define GLCP_CLKDISABLE 0x0012
+#define GLCP_CLK4ACK 0x0013
+#define GLCP_SYS_RSTPLL 0x0014
+#define GLCP_DOTPLL 0x0015
+#define GLCP_DBGCLKCTL 0x0016
+#define GLCP_REVID 0x0017
+#define GLCP_RAW_DIAG 0x0028
+#define GLCP_SETM0CTL 0x0040
+#define GLCP_SETN0CTL 0x0048
+#define GLCP_CMPVAL0 0x0050
+#define GLCP_CMPMASK0 0x0051
+#define GLCP_REGA 0x0058
+#define GLCP_REGB 0x0059
+#define GLCP_REGAMASK 0x005A
+#define GLCP_REGAVAL 0x005B
+#define GLCP_REGBMASK 0x005C
+#define GLCP_REGBVAL 0x005D
+#define GLCP_FIFOCTL 0x005E
+#define GLCP_DIAGCTL 0x005F
+#define GLCP_H0CTL 0x0060
+#define GLCP_XSTATE 0x0066
+#define GLCP_YSTATE 0x0067
+#define GLCP_ACTION0 0x0068
+
+/* GLCP_DOTPLL DEFINITIONS */
+
+#define GLCP_DOTPLL_RESET 0x00000001
+#define GLCP_DOTPLL_BYPASS 0x00008000
+#define GLCP_DOTPLL_HALFPIX 0x01000000
+#define GLCP_DOTPLL_LOCK 0x02000000
+#define GLCP_DOTPLL_VIPCLK 0x00008000
+#define GLCP_DOTPLL_DIV4 0x00010000
+
+/* GLCP DIAG DEFINITIONS */
+
+#define GLCP_MBD_DIAG_SEL0 0x00000007
+#define GLCP_MBD_DIAG_EN0 0x00008000
+#define GLCP_MBD_DIAG_SEL1 0x00070000
+#define GLCP_MBD_DIAG_EN1 0x80000000
+
+/*--------------------------------*/
+/* DISPLAY FILTER MSR DEFINITIONS */
+/*--------------------------------*/
+
+/* DISPLAY FILTER MBD_MSR_DIAG DEFINITIONS */
+
+#define DF_MBD_DIAG_SEL0 0x00007FFF
+#define DF_MBD_DIAG_EN0 0x00008000
+#define DF_MBD_DIAG_SEL1 0x7FFF0000
+#define DF_MBD_DIAG_EN1 0x80000000
+
+/* DISPLAY FILTER MBD_MSR_CONFIG DEFINITIONS */
+
+#define DF_CONFIG_FMT_MASK 0x00000038
+#define DF_CONFIG_FMT_CRT 0x00000000
+#define DF_CONFIG_FMT_FP 0x00000008
+
+/*----------------------------------------------------------------*/
+/* PCI DEFINITIONS */
+/*----------------------------------------------------------------*/
+
+#define PCI_VENDOR_DEVICE_GEODEGX 0x0028100B
+#define PCI_VENDOR_DEVICE_GEODEGX_VIDEO 0x0030100B
+#define PCI_VENDOR_DEVICE_GEODELX 0x20801022
+#define PCI_VENDOR_DEVICE_GEODELX_VIDEO 0x20811022
+#define PCI_VENDOR_5535 0x002B100B
+#define PCI_VENDOR_5536 0x20901022
+
+/*----------------------------------------------------------------*/
+/* VIP DEFINITIONS */
+/*----------------------------------------------------------------*/
+
+#define VIP_CONTROL1 0x00000000
+#define VIP_CONTROL2 0x00000004
+#define VIP_STATUS 0x00000008
+#define VIP_INTERRUPT 0x0000000C
+#define VIP_CURRENT_TARGET 0x00000010
+#define VIP_MAX_ADDRESS 0x00000014
+#define VIP_TASKA_VID_EVEN_BASE 0x00000018
+#define VIP_TASKA_VID_ODD_BASE 0x0000001C
+#define VIP_TASKA_VBI_EVEN_BASE 0x00000020
+#define VIP_TASKA_VBI_ODD_BASE 0x00000024
+#define VIP_TASKA_VID_PITCH 0x00000028
+#define VIP_CONTROL3 0x0000002C
+#define VIP_TASKA_V_OFFSET 0x00000030
+#define VIP_TASKA_U_OFFSET 0x00000034
+#define VIP_TASKB_VID_EVEN_BASE 0x00000038
+#define VIP_601_HORZ_END 0x00000038
+#define VIP_TASKB_VID_ODD_BASE 0x0000003C
+#define VIP_601_HORZ_START 0x0000003C
+#define VIP_TASKB_VBI_EVEN_BASE 0x00000040
+#define VIP_601_VBI_END 0x00000040
+#define VIP_TASKB_VBI_ODD_BASE 0x00000044
+#define VIP_601_VBI_START 0x00000044
+#define VIP_TASKB_VID_PITCH 0x00000048
+#define VIP_601_EVEN_START_STOP 0x00000048
+#define VIP_TASKB_V_OFFSET 0x00000050
+#define VIP_ODD_FIELD_DETECT 0x00000050
+#define VIP_TASKB_U_OFFSET 0x00000054
+#define VIP_ANC_MSG1_BASE 0x00000058
+#define VIP_ANC_MSG2_BASE 0x0000005C
+#define VIP_ANC_MSG_SIZE 0x00000060
+#define VIP_PAGE_OFFSET 0x00000068
+#define VIP_VERTICAL_START_STOP 0x0000006C
+#define VIP_601_ODD_START_STOP 0x0000006C
+#define VIP_FIFO_ADDRESS 0x00000070
+#define VIP_FIFO_DATA 0x00000074
+#define VIP_VSYNC_ERR_COUNT 0x00000078
+#define VIP_TASKA_U_EVEN_OFFSET 0x0000007C
+#define VIP_TASKA_V_EVEN_OFFSET 0x00000080
+
+/* INDIVIDUAL REGISTER BIT DEFINITIONS */
+/* Multibit register subsets are expressed as a mask and shift. */
+/* Single bit values are represented as a mask. */
+
+/* VIP_CONTROL1 REGISTER DEFINITIONS */
+
+#define VIP_CONTROL1_DEFAULT_ANC_FF 2
+#define VIP_CONTROL1_ANC_FF_MASK 0xE0000000
+#define VIP_CONTROL1_ANC_FF_SHIFT 29
+
+#define VIP_CONTROL1_DEFAULT_VID_FF 2
+#define VIP_CONTROL1_VID_FF_MASK 0x1F000000
+#define VIP_CONTROL1_VID_FF_SHIFT 24
+
+#define VIP_CONTROL1_VDE_FF_MASK 0x00F00000
+#define VIP_CONTROL1_VDE_FF_SHIFT 20
+
+#define VIP_CONTROL1_NON_INTERLACED (1L << 19)
+#define VIP_CONTROL1_MSG_STRM_CTRL (1L << 18)
+#define VIP_CONTROL1_DISABLE_ZERO_DETECT (1L << 17)
+#define VIP_CONTROL1_DISABLE_DECIMATION (1L << 16)
+
+#define VIP_CONTROL1_CAPTURE_ENABLE_MASK 0x0000FF00
+#define VIP_CONTROL1_CAPTURE_ENABLE_SHIFT 8
+
+#define VIP_CONTROL1_RUNMODE_MASK 0x000000E0
+#define VIP_CONTROL1_RUNMODE_SHIFT 5
+
+#define VIP_CONTROL1_PLANAR (1L << 4)
+
+#define VIP_CONTROL1_MODE_MASK 0x0000000E
+#define VIP_CONTROL1_MODE_SHIFT 1
+
+#define VIP_CONTROL1_RESET 0x00000001
+
+/* VIP_CONTROL2 REGISTER DEFINITIONS */
+
+#define VIP_CONTROL2_INVERT_POLARITY (1L << 31)
+#define VIP_CONTROL2_ADD_ERROR_ENABLE (1L << 30)
+#define VIP_CONTROL2_REPEAT_ENABLE (1L << 29)
+#define VIP_CONTROL2_SWC_ENABLE (1L << 28)
+#define VIP_CONTROL2_ANC10 (1L << 27)
+#define VIP_CONTROL2_ANCPEN (1L << 26)
+#define VIP_CONTROL2_LOOPBACK_ENABLE (1L << 25)
+#define VIP_CONTROL2_FIFO_ACCESS (1L << 24)
+#define VIP_CONTROL2_VERTERROR_ENABLE (1L << 15)
+
+#define VIP_CONTROL2_PAGECNT_MASK 0x00E00000
+#define VIP_CONTROL2_PAGECNT_SHIFT 21
+
+#define VIP_CONTROL2_DEFAULT_ANCTH 5
+#define VIP_CONTROL2_ANCTH_MASK 0x001F0000
+#define VIP_CONTROL2_ANCTH_SHIFT 16
+
+#define VIP_CONTROL2_DEFAULT_VIDTH_420 19
+#define VIP_CONTROL2_DEFAULT_VIDTH_422 19
+#define VIP_CONTROL2_VIDTH_MASK 0x00007F00
+#define VIP_CONTROL2_VIDTH_SHIFT 8
+
+#define VIP_CONTROL2_SYNC2PIN_MASK 0x000000E0
+#define VIP_CONTROL2_SYNC2PIN_SHIFT 5
+
+#define VIP_CONTROL2_FIELD2VG_MASK 0x00000018
+#define VIP_CONTROL2_FIELD2VG_SHIFT 3
+
+#define VIP_CONTROL2_SYNC2VG_MASK 0x00000007
+#define VIP_CONTROL2_SYNC2VG_SHIFT 0
+
+/* VIP_CONTROL3 REGISTER DEFINITIONS */
+
+#define VIP_CONTROL3_PLANAR_DEINT 0x00000400
+#define VIP_CONTROL3_BASE_UPDATE 0x00000200
+#define VIP_CONTROL3_DISABLE_OVERFLOW 0x00000100
+#define VIP_CONTROL3_DECIMATE_EVEN 0x00000080
+#define VIP_CONTROL3_TASK_POLARITY 0x00000040
+#define VIP_CONTROL3_VSYNC_POLARITY 0x00000020
+#define VIP_CONTROL3_HSYNC_POLARITY 0x00000010
+#define VIP_CONTROL3_FIFO_RESET 0x00000001
+
+/* VIP_STATUS REGISTER DEFINITIONS */
+
+#define VIP_STATUS_ANC_COUNT_MASK 0xFF000000
+#define VIP_STATUS_ANC_COUNT_SHIFT 24
+
+#define VIP_STATUS_FIFO_ERROR 0x00700000
+#define VIP_STATUS_ERROR_SHIFT 20
+#define VIP_STATUS_DEC_COUNT (1L << 18)
+#define VIP_STATUS_SYNCOUT (1L << 17)
+#define VIP_STATUS_BASEREG_NOTUPDT (1L << 16)
+#define VIP_STATUS_MSGBUFF_ERR (1L << 14)
+#define VIP_STATUS_MSGBUFF2_FULL (1L << 13)
+#define VIP_STATUS_MSGBUFF1_FULL (1L << 12)
+#define VIP_STATUS_WRITES_COMPLETE (1L << 9)
+#define VIP_STATUS_FIFO_EMPTY (1L << 8)
+#define VIP_STATUS_FIELD (1L << 4)
+#define VIP_STATUS_VBLANK (1L << 3)
+
+#define VIP_STATUS_RUN_MASK 0x00000007
+#define VIP_STATUS_RUN_SHIFT 0
+
+/* VIP_CURRENT_TARGET REGISTER DEFINITIONS */
+
+#define VIP_CTARGET_TLINE_MASK 0xFFFF0000
+#define VIP_CTARGET_TLINE_SHIFT 16
+
+#define VIP_CTARGET_CLINE_MASK 0x0000FFFF
+#define VIP_CTARGET_CLINE_SHIFT 0
+
+/* VIP_MAX_ADDRESS REGISTER DEFINITIONS */
+
+#define VIP_MAXADDR_MASK 0xFFFFFFFF
+#define VIP_MAXADDR_SHIFT 0
+
+/* VIP BUFFER PITCH DEFINITIONS */
+
+#define VIP_TASK_PITCH_MASK 0x0000FFFF
+#define VIP_TASK_PITCH_SHIFT 0
+
+/* VERTICAL START/STOP */
+
+#define VIP_VSTART_VERTEND_MASK 0x0FFF0000
+#define VIP_VSTART_VERTEND_SHIFT 16
+
+#define VIP_VSTART_VERTSTART_MASK 0x00000FFF
+#define VIP_VSTART_VERTSTART_SHIFT 0
+
+/* VIP FIFO ADDRESS DEFINITIONS */
+
+#define VIP_FIFO_ADDRESS_MASK 0x000000FF
+#define VIP_FIFO_ADDRESS_SHIFT 0
+
+/* VIP VSYNC ERROR DEFINITIONS */
+
+#define VIP_VSYNC_ERR_WINDOW_MASK 0xFF000000
+#define VIP_VSYNC_ERR_WINDOW_SHIFT 24
+
+#define VIP_VSYNC_ERR_COUNT_MASK 0x00FFFFFF
+#define VIP_VSYNC_ERR_COUNT_SHIFT 0
+
+/*---------------------*/
+/* VIP MSR DEFINITIONS */
+/*---------------------*/
+
+/* CAPABILITIES */
+
+#define VIP_MSR_CAP_NSMI_MASK 0xF8000000
+#define VIP_MSR_CAP_NSMI_SHIFT 27
+#define VIP_MSR_CAP_NCLK_MASK 0x07000000
+#define VIP_MSR_CAP_NCLK_SHIFT 24
+#define VIP_MSR_CAP_DEVID_MASK 0x00FFFF00
+#define VIP_MSR_CAP_DEVID_SHIFT 8
+#define VIP_MSR_CAP_REVID_MASK 0x000000FF
+#define VIP_MSR_CAP_REVID_SHIFT 0
+
+/* MASTER CONFIG */
+
+#define VIP_MSR_MCR_SECOND_PRIORITY_MASK 0x00000700
+#define VIP_MSR_MCR_SECOND_PRIORITY_SHIFT 8
+#define VIP_MSR_MCR_PRIMARY_PRIORITY_MASK 0x00000070
+#define VIP_MSR_MCR_PRIMARY_PRIORITY_SHIFT 4
+#define VIP_MSR_MCR_PID_MASK 0x00000007
+#define VIP_MSR_MCR_PID_SHIFT 0
+
+/* VIP SMI */
+
+#define VIP_MSR_SMI_FIFO_OVERFLOW (1L << 29)
+#define VIP_MSR_SMI_FIFO_THRESHOLD (1L << 28)
+#define VIP_MSR_SMI_LONGLINE (1L << 27)
+#define VIP_MSR_SMI_VERTICAL_TIMING (1L << 26)
+#define VIP_MSR_SMI_ACTIVE_PIXELS (1L << 25)
+#define VIP_MSR_SMI_CLOCK_INPUT (1L << 24)
+#define VIP_MSR_SMI_ANC_CHECKSUM_PARITY (1L << 23)
+#define VIP_MSR_SMI_MSG_BUFFER_FULL (1L << 22)
+#define VIP_MSR_SMI_END_VBLANK (1L << 21)
+#define VIP_MSR_SMI_START_VBLANK (1L << 20)
+#define VIP_MSR_SMI_START_EVEN (1L << 19)
+#define VIP_MSR_SMI_START_ODD (1L << 18)
+#define VIP_MSR_SMI_LINE_MATCH_TARGET (1L << 17)
+#define VIP_MSR_SMI_GLINK (1L << 16)
+
+/* VIP ERROR */
+
+#define VIP_MSR_ERROR_ADDRESS_MASK (1L << 17)
+#define VIP_MSR_ERROR_ADDRESS_SHIFT 17
+#define VIP_MSR_ERROR_ADDRESS_ENABLE (1L << 1)
+#define VIP_MSR_ERROR_ADDRESS_EN_SHIFT 1
+#define VIP_MSR_ERROR_TYPE_MASK (1L << 16)
+#define VIP_MSR_ERROR_TYPE_SHIFT 16
+#define VIP_MSR_ERROR_TYPE_ENABLE 1
+#define VIP_MSR_ERROR_TYPE_EN_SHIFT 0
+
+/* VIP POWER */
+
+#define VIP_MSR_POWER_GLINK (1L << 0)
+#define VIP_MSR_POWER_CLOCK (1L << 2)
+
+/* VIP DIAG */
+
+#define VIP_MSR_DIAG_BIST_WMASK 0x00000003
+#define VIP_MSR_DIAG_BIST_RMASK 0x00000007
+#define VIP_MSR_DIAG_BIST_SHIFT 0
+
+#define VIP_MSR_DIAG_MSB_ENABLE (1L << 31)
+#define VIP_MSR_DIAG_SEL_UPPER_MASK 0x7FFF0000
+#define VIP_MSR_DIAG_SEL_UPPER_SHIFT 16
+#define VIP_MSR_DIAG_LSB_ENABLE (1L << 15)
+#define VIP_MSR_DIAG_SEL_LOWER_MASK 0x00007FFF
+#define VIP_MSR_DIAG_SEL_LOWER_SHIFT 0
+
+/*----------------------------------------------------------------*/
+/* VOP DEFINITIONS */
+/*----------------------------------------------------------------*/
+
+#define VOP_CONFIGURATION 0x00000800
+#define VOP_SIGNATURE 0x00000808
+
+/* VOP_CONFIGURATION BIT DEFINITIONS */
+
+#define VOP_CONFIG_SWAPVBI 0x01000000
+#define VOP_CONFIG_RGBMODE 0x00200000
+#define VOP_CONFIG_SIGVAL 0x00100000
+#define VOP_CONFIG_INVERT_DISPE 0x00080000
+#define VOP_CONFIG_INVERT_VSYNC 0x00040000
+#define VOP_CONFIG_INVERT_HSYNC 0x00020000
+#define VOP_CONFIG_SWAPUV 0x00010000
+#define VOP_CONFIG_VSYNC_MASK 0x0000C000
+#define VOP_CONFIG_DISABLE_DECIMATE 0x00002000
+#define VOP_CONFIG_ENABLE_601 0x00001000
+#define VOP_CONFIG_VBI 0x00000800
+#define VOP_CONFIG_TASK 0x00000200
+#define VOP_CONFIG_SIG_FREE_RUN 0x00000100
+#define VOP_CONFIG_ENABLE_SIGNATURE 0x00000080
+#define VOP_CONFIG_SC_COMPATIBLE 0x00000040
+#define VOP_CONFIG_422_COSITED 0x00000000
+#define VOP_CONFIG_422_INTERSPERSED 0x00000010
+#define VOP_CONFIG_422_ALTERNATING 0x00000020
+#define VOP_CONFIG_422_MASK 0x00000030
+#define VOP_CONFIG_EXTENDED_SAV 0x00000008
+#define VOP_CONFIG_VIP2_16BIT 0x00000004
+#define VOP_CONFIG_DISABLED 0x00000000
+#define VOP_CONFIG_VIP1_1 0x00000001
+#define VOP_CONFIG_VIP2_0 0x00000002
+#define VOP_CONFIG_CCIR656 0x00000003
+#define VOP_CONFIG_MODE_MASK 0x00000003
+
+
+#endif
diff -Nru kernel-2.6.18geode-hurricane.orig/lib/cimarron/cim/cim_rtns.h kernel-2.6.18geode-hurricane/lib/cimarron/cim/cim_rtns.h
--- kernel-2.6.18geode-hurricane.orig/lib/cimarron/cim/cim_rtns.h 1970-01-01 01:00:00.000000000 +0100
+++ kernel-2.6.18geode-hurricane/lib/cimarron/cim/cim_rtns.h 2006-12-01 13:21:21.000000000 +0100
@@ -0,0 +1,338 @@
+ /*
+ *
+ * Copyright (C) 2005 Advanced Micro Devices, Inc. All Rights Reserved.
+ *
+ *
+ *
+ *
+ *
+ *
+ * Cimarron function prototypes.
+ *
+ *
+ */
+
+#ifndef _cim_rtns_h
+#define _cim_rtns_h
+
+/* INCLUDE USER PARAMETER DEFINITIONS */
+
+#include "cim_parm.h"
+
+/* COMPILER OPTION FOR C++ PROGRAMS */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*--------------------------*/
+/* CIMARRON MEMORY POINTERS */
+/*--------------------------*/
+
+extern unsigned char *cim_gp_ptr;
+extern unsigned char *cim_fb_ptr;
+extern unsigned char *cim_cmd_base_ptr;
+extern unsigned char *cim_cmd_ptr;
+extern unsigned char *cim_vid_ptr;
+extern unsigned char *cim_vip_ptr;
+extern unsigned char *cim_vg_ptr;
+
+/*----------------------------------------*/
+/* INITIALIZATION ROUTINE DEFINITIONS */
+/*----------------------------------------*/
+
+int init_detect_cpu (unsigned long *cpu_revision, unsigned long *companion_revision);
+unsigned long init_read_pci (unsigned long address);
+int init_read_base_addresses (INIT_BASE_ADDRESSES *base_addresses);
+int init_read_cpu_frequency (unsigned long *cpu_frequency);
+
+/*----------------------------------------*/
+/* GRAPHICS PROCESSOR ROUTINE DEFINITIONS */
+/*----------------------------------------*/
+
+void gp_set_limit_on_buffer_lead (unsigned long lead);
+void gp_set_command_buffer_base (unsigned long address, unsigned long start,
+ unsigned long stop);
+void gp_set_frame_buffer_base (unsigned long address, unsigned long size);
+void gp_set_bpp (int bpp);
+void gp_declare_blt (unsigned long flags);
+void gp_declare_vector (unsigned long flags);
+void gp_write_parameters (void);
+void gp_set_raster_operation (unsigned char ROP);
+void gp_set_alpha_operation (int alpha_operation, int alpha_type, int channel,
+ int apply_alpha, unsigned char alpha);
+void gp_set_solid_pattern (unsigned long color);
+void gp_set_mono_pattern (unsigned long bgcolor, unsigned long fgcolor,
+ unsigned long data0, unsigned long data1, int transparent, int x, int y);
+void gp_set_pattern_origin (int x, int y);
+void gp_set_color_pattern (unsigned long *pattern, int format, int x, int y);
+void gp_set_mono_source (unsigned long bgcolor, unsigned long fgcolor,
+ int transparent);
+void gp_set_solid_source (unsigned long color);
+void gp_set_source_transparency (unsigned long color, unsigned long mask);
+void gp_program_lut (unsigned long *colors, int full_lut);
+void gp_set_vector_pattern (unsigned long pattern, unsigned long color, int length);
+void gp_set_strides (unsigned long dst_stride, unsigned long src_stride);
+void gp_set_source_format (int format);
+void gp_pattern_fill (unsigned long dstoffset, unsigned long width, unsigned long height);
+void gp_screen_to_screen_blt (unsigned long dstoffset, unsigned long srcoffset,
+ unsigned long width, unsigned long height, int flags);
+void gp_screen_to_screen_convert (unsigned long dstoffset, unsigned long srcoffset,
+ unsigned long width, unsigned long height, int nibble);
+void gp_color_bitmap_to_screen_blt (unsigned long dstoffset, unsigned long srcx,
+ unsigned long width, unsigned long height, unsigned char *data, long pitch);
+void gp_color_convert_blt (unsigned long dstoffset, unsigned long srcx,
+ unsigned long width, unsigned long height, unsigned char *data, long pitch);
+void gp_custom_convert_blt (unsigned long dstoffset, unsigned long srcx,
+ unsigned long width, unsigned long height, unsigned char *data, long pitch);
+void gp_rotate_blt (unsigned long dstoffset, unsigned long srcoffset,
+ unsigned long width, unsigned long height, int degrees);
+void gp_mono_bitmap_to_screen_blt (unsigned long dstoffset, unsigned long srcx,
+ unsigned long width, unsigned long height, unsigned char *data, long stride);
+void gp_text_blt (unsigned long dstoffset, unsigned long width,
+ unsigned long height, unsigned char *data);
+void gp_mono_expand_blt (unsigned long dstoffset, unsigned long srcoffset,
+ unsigned long srcx, unsigned long width, unsigned long height, int byte_packed);
+void gp_antialiased_text (unsigned long dstoffset, unsigned long srcx,
+ unsigned long width, unsigned long height, unsigned char *data, long stride,
+ int fourbpp);
+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);
+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);
+void gp_bresenham_line (unsigned long dstoffset, unsigned short length,
+ unsigned short initerr, unsigned short axialerr, unsigned short diagerr,
+ unsigned long flags);
+void gp_line_from_endpoints (unsigned long dstoffset, unsigned long x0,
+ unsigned long y0, unsigned long x1, unsigned long y1, int inclusive);
+
+int gp_test_blt_pending (void);
+void gp_wait_blt_pending (void);
+void gp_wait_until_idle (void);
+int gp_test_blt_busy (void);
+void gp_save_state (GP_SAVE_RESTORE *gp_state);
+void gp_restore_state (GP_SAVE_RESTORE *gp_state);
+
+/*----------------------------------------*/
+/* VIDEO GENERATOR ROUTINE DEFINITIONS */
+/*----------------------------------------*/
+
+int vg_delay_milliseconds (unsigned long ms);
+int vg_set_display_mode (unsigned long src_width, unsigned long src_height,
+ unsigned long dst_width, unsigned long dst_height, int bpp, int hz,
+ unsigned long flags);
+int vg_set_panel_mode (unsigned long src_width, unsigned long src_height,
+ unsigned long dst_width, unsigned long dst_height,
+ unsigned long panel_width, unsigned long panel_height,
+ int bpp, unsigned long flags);
+int vg_set_tv_mode (unsigned long *src_width, unsigned long *src_height,
+ unsigned long encoder, unsigned long tvres, int bpp, unsigned long flags,
+ unsigned long h_overscan, unsigned long v_overscan);
+int vg_set_custom_mode (VG_DISPLAY_MODE *mode_params, int bpp);
+int vg_set_display_bpp (int bpp);
+int vg_get_display_mode_index (VG_QUERY_MODE *query);
+int vg_get_display_mode_information (unsigned int index, VG_DISPLAY_MODE *vg_mode);
+int vg_get_display_mode_count (void);
+int vg_get_current_display_mode (VG_DISPLAY_MODE *current_display, int *bpp);
+int vg_set_scaler_filter_coefficients (long h_taps[][5], long v_taps[][3]);
+int vg_configure_flicker_filter (unsigned long flicker_strength, int flicker_alpha);
+int vg_set_clock_frequency (unsigned long frequency, unsigned long pll_flags);
+int vg_set_border_color (unsigned long border_color);
+int vg_set_cursor_enable(int enable);
+int vg_set_mono_cursor_colors (unsigned long bkcolor, unsigned long fgcolor);
+int vg_set_cursor_position(long xpos, long ypos, VG_PANNING_COORDINATES *panning);
+int vg_set_mono_cursor_shape32(unsigned long memoffset, unsigned long *andmask,
+ unsigned long *xormask, unsigned long x_hotspot, unsigned long y_hotspot);
+int vg_set_mono_cursor_shape64(unsigned long memoffset, unsigned long *andmask,
+ unsigned long *xormask, unsigned long x_hotspot, unsigned long y_hotspot);
+int vg_set_color_cursor_shape (unsigned long memoffset, unsigned char *data,
+ unsigned long width, unsigned long height, long pitch,
+ unsigned long x_hotspot, unsigned long y_hotspot);
+int vg_pan_desktop (unsigned long x, unsigned long y, VG_PANNING_COORDINATES *panning);
+int vg_set_display_offset (unsigned long address);
+int vg_set_display_pitch (unsigned long pitch);
+int vg_set_display_palette_entry (unsigned long index, unsigned long palette);
+int vg_set_display_palette (unsigned long *palette);
+int vg_set_compression_enable (int enable);
+int vg_configure_compression (VG_COMPRESSION_DATA *comp_data);
+int vg_test_timing_active (void);
+int vg_test_vertical_active (void);
+int vg_wait_vertical_blank(void);
+int vg_test_even_field(void);
+int vg_configure_line_interrupt (VG_INTERRUPT_PARAMS *interrupt_info);
+unsigned long vg_test_and_clear_interrupt (void);
+unsigned long vg_test_flip_status (void);
+int vg_save_state (VG_SAVE_RESTORE *vg_state);
+int vg_restore_state (VG_SAVE_RESTORE *vg_state);
+
+/*----------------------------------------*/
+/* VIDEO GENERATOR READ ROUTINES */
+/*----------------------------------------*/
+
+unsigned long vg_read_graphics_crc (int crc_source);
+unsigned long vg_read_window_crc (int crc_source, unsigned long x, unsigned long y,
+ unsigned long width, unsigned long height);
+int vg_get_scaler_filter_coefficients (long h_taps[][5], long v_taps[][3]);
+int vg_get_flicker_filter_configuration (unsigned long *strength, int *flicker_alpha);
+unsigned long vg_get_display_pitch (void);
+unsigned long vg_get_frame_buffer_line_size (void);
+unsigned long vg_get_current_vline (void);
+unsigned long vg_get_display_offset (void);
+int vg_get_cursor_info (VG_CURSOR_DATA *cursor_data);
+int vg_get_display_palette_entry (unsigned long index, unsigned long *entry);
+unsigned long vg_get_border_color (void);
+int vg_get_display_palette (unsigned long *palette);
+int vg_get_compression_info (VG_COMPRESSION_DATA *comp_data);
+int vg_get_compression_enable (void);
+int vg_get_valid_bit (int line);
+
+/*----------------------------------------*/
+/* DISPLAY FILTER ROUTINE DEFINITIONS */
+/*----------------------------------------*/
+
+int df_set_crt_enable (int crt_output);
+int df_set_panel_enable (int panel_output);
+int df_configure_video_source (DF_VIDEO_SOURCE_PARAMS *video_source_odd,
+ DF_VIDEO_SOURCE_PARAMS *video_source_even);
+int df_set_video_offsets (int even, unsigned long y_offset,
+ unsigned long u_offset, unsigned long v_offset);
+int df_set_video_scale (unsigned long src_width, unsigned long src_height,
+ unsigned long dst_width, unsigned long dst_height, unsigned long flags);
+int df_set_video_position (DF_VIDEO_POSITION *video_window);
+int df_set_video_filter_coefficients (long taps[][4], int phase256);
+int df_set_video_enable (int enable, unsigned long flags);
+int df_set_video_color_key (unsigned long key, unsigned long mask, int graphics);
+int df_set_video_palette (unsigned long *palette);
+int df_set_video_palette_entry (unsigned long index, unsigned long palette);
+int df_configure_video_cursor_color_key (DF_VIDEO_CURSOR_PARAMS *cursor_color_key);
+int df_set_video_cursor_color_key_enable (int enable);
+int df_configure_alpha_window (int window, DF_ALPHA_REGION_PARAMS *alpha_data);
+int df_set_alpha_window_enable (int window, int enable);
+int df_set_no_ck_outside_alpha (int enable);
+int df_set_video_request (unsigned long x, unsigned long y);
+int df_set_output_color_space (int color_space);
+int df_set_output_path (int format);
+unsigned long df_test_video_flip_status (void);
+int df_save_state (DF_SAVE_RESTORE *gp_state);
+int df_restore_state (DF_SAVE_RESTORE *gp_state);
+
+/*----------------------------------------*/
+/* DISPLAY FILTER READ ROUTINES */
+/*----------------------------------------*/
+
+unsigned long df_read_composite_crc (int crc_source);
+unsigned long df_read_composite_window_crc (unsigned long x, unsigned long y,
+ unsigned long width, unsigned long height, int source);
+unsigned long df_read_panel_crc (void);
+int df_get_video_enable (int *enable, unsigned long *flags);
+int df_get_video_source_configuration (DF_VIDEO_SOURCE_PARAMS *video_source_odd,
+ DF_VIDEO_SOURCE_PARAMS *video_source_even);
+int df_get_video_position (DF_VIDEO_POSITION *video_window);
+int df_get_video_scale (unsigned long *x_scale, unsigned long *y_scale);
+int df_get_video_filter_coefficients (long taps[][4], int *phase256);
+int df_get_video_color_key (unsigned long *key, unsigned long *mask, int *graphics);
+int df_get_video_palette_entry(unsigned long index, unsigned long *palette);
+int df_get_video_palette (unsigned long *palette);
+int df_get_video_cursor_color_key (DF_VIDEO_CURSOR_PARAMS *cursor_color_key);
+int df_get_video_cursor_color_key_enable (void);
+int df_get_alpha_window_configuration (int window, DF_ALPHA_REGION_PARAMS *alpha_data);
+int df_get_alpha_window_enable (int window);
+int df_get_video_request (unsigned long *x, unsigned long *y);
+int df_get_output_color_space (int *color_space);
+
+/*----------------------------------------*/
+/* MSR ROUTINE DEFINITIONS */
+/*----------------------------------------*/
+
+int msr_init_table (void);
+int msr_create_geodelink_table (GEODELINK_NODE *gliu_nodes);
+int msr_create_device_list (GEODELINK_NODE *gliu_nodes, int max_devices);
+int msr_read64 (unsigned long device, unsigned long msr_register,
+ Q_WORD *msr_value);
+int msr_write64 (unsigned long device, unsigned long msr_register,
+ Q_WORD *msr_value);
+
+/*----------------------------------------*/
+/* VIP ROUTINE DEFINITIONS */
+/*----------------------------------------*/
+
+int vip_initialize (VIPSETMODEBUFFER *buffer);
+int vip_update_601_params (VIP_601PARAMS *buffer);
+int vip_terminate (void);
+int vip_configure_capture_buffers (int buffer_type, VIPINPUTBUFFER *buffer);
+int vip_toggle_video_offsets (int buffer_type, VIPINPUTBUFFER *buffer);
+int vip_max_address_enable (unsigned long max_address, int enable);
+int vip_set_interrupt_enable (unsigned long mask, int enable);
+unsigned long vip_get_interrupt_state (void);
+int vip_set_capture_state (unsigned long state);
+int vip_set_vsync_error (unsigned long vertical_count, unsigned long window_before,
+ unsigned long window_after, int enable);
+int vip_configure_fifo (unsigned long fifo_type, unsigned long fifo_size);
+int vip_set_loopback_enable (int bEnable);
+int vip_configure_genlock (VIPGENLOCKBUFFER *buffer);
+int vip_set_genlock_enable (int bEnable);
+int vip_configure_pages (int page_count, unsigned long page_offset);
+int vip_set_interrupt_line (int line);
+int vip_reset (void);
+int vip_set_subwindow_enable (VIPSUBWINDOWBUFFER *buffer);
+int vip_reset_interrupt_state (unsigned long interrupt_mask);
+
+int vip_save_state(VIPSTATEBUFFER *save_buffer);
+int vip_restore_state(VIPSTATEBUFFER *restore_buffer);
+int vip_set_power_characteristics (VIPPOWERBUFFER *buffer);
+int vip_set_priority_characteristics (VIPPRIORITYBUFFER *buffer);
+int vip_set_debug_characteristics (VIPDEBUGBUFFER *buffer);
+int vip_test_genlock_active (void);
+int vip_test_signal_status (void);
+unsigned long vip_get_current_field (void);
+
+/*----------------------------------------*/
+/* VIP READ ROUTINES */
+/*----------------------------------------*/
+
+int vip_get_current_mode (VIPSETMODEBUFFER *buffer);
+int vip_get_601_configuration (VIP_601PARAMS *buffer);
+int vip_get_buffer_configuration (int buffer_type, VIPINPUTBUFFER *buffer);
+int vip_get_genlock_configuration (VIPGENLOCKBUFFER *buffer);
+int vip_get_genlock_enable (void);
+int vip_is_buffer_update_latched (void);
+unsigned long vip_get_capture_state (void);
+unsigned long vip_get_current_line (void);
+unsigned long vip_read_fifo (unsigned long fifo_address);
+int vip_write_fifo (unsigned long fifo_address, unsigned long fifo_data);
+int vip_enable_fifo_access (int enable);
+int vip_get_capability_characteristics (VIPCAPABILITIESBUFFER *buffer);
+int vip_get_power_characteristics (VIPPOWERBUFFER *buffer);
+int vip_get_priority_characteristics (VIPPRIORITYBUFFER *buffer);
+
+/*----------------------------------------*/
+/* VOP ROUTINE DEFINITIONS */
+/*----------------------------------------*/
+
+int vop_set_vbi_window (VOPVBIWINDOWBUFFER *buffer);
+int vop_enable_vbi_output (int enable);
+int vop_set_configuration (VOPCONFIGURATIONBUFFER *config);
+int vop_save_state(VOPSTATEBUFFER *save_buffer);
+int vop_restore_state(VOPSTATEBUFFER *save_buffer);
+
+/*----------------------------------------*/
+/* VOP READ ROUTINES */
+/*----------------------------------------*/
+
+int vop_get_current_mode (VOPCONFIGURATIONBUFFER *config);
+int vop_get_vbi_configuration (VOPVBIWINDOWBUFFER *buffer);
+int vop_get_vbi_enable (void);
+unsigned long vop_get_crc (void);
+unsigned long vop_read_vbi_crc(void);
+
+/* CLOSE BRACKET FOR C++ COMPLILATION */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
diff -Nru kernel-2.6.18geode-hurricane.orig/lib/cimarron/cim/cim_version.h kernel-2.6.18geode-hurricane/lib/cimarron/cim/cim_version.h
--- kernel-2.6.18geode-hurricane.orig/lib/cimarron/cim/cim_version.h 1970-01-01 01:00:00.000000000 +0100
+++ kernel-2.6.18geode-hurricane/lib/cimarron/cim/cim_version.h 2006-12-01 13:21:21.000000000 +0100
@@ -0,0 +1,15 @@
+ /*
+ *
+ * Copyright (C) 2005 Advanced Micro Devices, Inc. All Rights Reserved.
+ *
+ *
+ *
+ *
+ *
+ *
+ * Cimarron Version information
+ *
+ *
+ */
+
+#define CIMARRON_REVISION 30102
\ No newline at end of file
diff -Nru kernel-2.6.18geode-hurricane.orig/lib/cimarron/cim/cim_vg.c kernel-2.6.18geode-hurricane/lib/cimarron/cim/cim_vg.c
--- kernel-2.6.18geode-hurricane.orig/lib/cimarron/cim/cim_vg.c 1970-01-01 01:00:00.000000000 +0100
+++ kernel-2.6.18geode-hurricane/lib/cimarron/cim/cim_vg.c 2006-12-01 13:21:21.000000000 +0100
@@ -0,0 +1,3589 @@
+ /*
+ *
+ * Copyright (C) 2005 Advanced Micro Devices, Inc. All Rights Reserved.
+ *
+ *
+ *
+ *
+ *
+ *
+ * Cimarron display controller routines. These routines program the display
+ * mode and configure the hardware cursor and video buffers.
+ *
+ *
+ */
+
+/*---------------------*/
+/* CIMARRON VG GLOBALS */
+/*---------------------*/
+
+CIMARRON_STATIC unsigned long vg3_x_hotspot = 0;
+CIMARRON_STATIC unsigned long vg3_y_hotspot = 0;
+CIMARRON_STATIC unsigned long vg3_cursor_offset = 0;
+CIMARRON_STATIC unsigned long vg3_mode_width = 0;
+CIMARRON_STATIC unsigned long vg3_mode_height = 0;
+CIMARRON_STATIC unsigned long vg3_panel_width = 0;
+CIMARRON_STATIC unsigned long vg3_panel_height = 0;
+CIMARRON_STATIC unsigned long vg3_delta_x = 0;
+CIMARRON_STATIC unsigned long vg3_delta_y = 0;
+CIMARRON_STATIC unsigned long vg3_bpp = 0;
+
+CIMARRON_STATIC unsigned long vg3_color_cursor = 0;
+CIMARRON_STATIC unsigned long vg3_panel_enable = 0;
+
+/*---------------------------------------------------------------------------
+ * vg_delay_milliseconds
+ *
+ * This routine delays for a number of milliseconds based on a crude
+ * delay loop.
+ *---------------------------------------------------------------------------*/
+
+int vg_delay_milliseconds (unsigned long ms)
+{
+ /* ASSUME 500 MHZ 20 CLOCKS PER READ */
+
+ unsigned long loop = ms * 25000;
+ while (loop-- > 0)
+ {
+ READ_REG32 (DC3_UNLOCK);
+ }
+ return CIM_STATUS_OK;
+}
+
+/*---------------------------------------------------------------------------
+ * vg_set_display_mode
+ *
+ * This routine sets a CRT display mode using predefined Cimarron timings. The
+ * source width and height are specified to allow scaling.
+ *---------------------------------------------------------------------------*/
+
+int vg_set_display_mode (unsigned long src_width, unsigned long src_height,
+ unsigned long dst_width, unsigned long dst_height, int bpp, int hz,
+ unsigned long flags)
+{
+ VG_QUERY_MODE crt_query;
+ VG_DISPLAY_MODE crt_mode;
+ int mode;
+
+ crt_query.active_width = dst_width;
+ crt_query.active_height = dst_height;
+ crt_query.bpp = bpp;
+ crt_query.hz = hz;
+ crt_query.query_flags = VG_QUERYFLAG_ACTIVEWIDTH |
+ VG_QUERYFLAG_ACTIVEHEIGHT |
+ VG_QUERYFLAG_BPP |
+ VG_QUERYFLAG_REFRESH;
+
+ mode = vg_get_display_mode_index (&crt_query);
+ if (mode >= 0)
+ {
+ crt_mode = CimarronDisplayModes[mode];
+ crt_mode.src_width = src_width;
+ crt_mode.src_height = src_height;
+
+ /* ADD USER-REQUESTED FLAGS */
+
+ crt_mode.flags |= (flags & VG_MODEFLAG_VALIDUSERFLAGS);
+
+ if (flags & VG_MODEFLAG_OVERRIDE_BAND)
+ {
+ crt_mode.flags &= ~VG_MODEFLAG_BANDWIDTHMASK;
+ crt_mode.flags |= (flags & VG_MODEFLAG_BANDWIDTHMASK);
+ }
+ if (flags & VG_MODEFLAG_INT_OVERRIDE)
+ {
+ crt_mode.flags &= ~VG_MODEFLAG_INT_MASK;
+ crt_mode.flags |= (flags & VG_MODEFLAG_INT_MASK);
+ }
+
+ return vg_set_custom_mode (&crt_mode, bpp);
+ }
+ return CIM_STATUS_ERROR;
+}
+
+/*---------------------------------------------------------------------------
+ * vg_set_panel_mode
+ *
+ * This routine sets a panel mode using predefined Cimarron fixed timings. The
+ * source width and height specify the width and height of the data in the frame
+ * buffer. The destination width and height specify the width and height of
+ * the active data to be displayed. The panel width and height specify the
+ * dimensions of the panel. This interface allows the user to scale or center
+ * graphics data or both. To perform scaling, the src width or height should
+ * be different than the destination width or height. To perform centering or
+ * panning, the destination width and height should be different than the panel
+ * resolution.
+ *---------------------------------------------------------------------------*/
+
+int vg_set_panel_mode (unsigned long src_width, unsigned long src_height,
+ unsigned long dst_width, unsigned long dst_height,
+ unsigned long panel_width, unsigned long panel_height,
+ int bpp, unsigned long flags)
+{
+ unsigned long sync_width;
+ unsigned long sync_offset;
+ VG_QUERY_MODE panel_query;
+ VG_DISPLAY_MODE panel_mode;
+ int mode;
+
+ /* SEARCH CIMARRON'S TABLE OF PREDEFINED PANEL MODES */
+ /* If the destination resolution is larger than the panel resolution, */
+ /* panning will be performed. However, the timings for a panned mode */
+ /* are identical to the timings without panning. To save space in the */
+ /* mode tables, there are no additional table entries for modes with */
+ /* panning. Instead, we read the timings for a mode without panning */
+ /* and override the structure entries that specify the width and */
+ /* height of the mode. We perform a similar procedure for centered */
+ /* modes, except that certain timing parameters are dynamically */
+ /* calculated. */
+
+ panel_query.active_width = panel_width;
+ panel_query.active_height = panel_height;
+ panel_query.panel_width = panel_width;
+ panel_query.panel_height = panel_height;
+ panel_query.bpp = bpp;
+ panel_query.query_flags = VG_QUERYFLAG_ACTIVEWIDTH |
+ VG_QUERYFLAG_ACTIVEHEIGHT |
+ VG_QUERYFLAG_PANELWIDTH |
+ VG_QUERYFLAG_PANELHEIGHT |
+ VG_QUERYFLAG_PANEL |
+ VG_QUERYFLAG_BPP;
+
+ mode = vg_get_display_mode_index (&panel_query);
+
+ /* COPY THE DATA FROM THE MODE TABLE TO A TEMPORARY STRUCTURE */
+
+ if (mode >= 0)
+ {
+ panel_mode = CimarronDisplayModes[mode];
+ panel_mode.mode_width = dst_width;
+ panel_mode.mode_height = dst_height;
+ panel_mode.src_width = src_width;
+ panel_mode.src_height = src_height;
+
+ /* ADD USER-REQUESTED FLAGS */
+
+ panel_mode.flags |= (flags & VG_MODEFLAG_VALIDUSERFLAGS);
+
+ if (flags & VG_MODEFLAG_OVERRIDE_BAND)
+ {
+ panel_mode.flags &= ~VG_MODEFLAG_BANDWIDTHMASK;
+ panel_mode.flags |= (flags & VG_MODEFLAG_BANDWIDTHMASK);
+ }
+ if (flags & VG_MODEFLAG_INT_OVERRIDE)
+ {
+ panel_mode.flags &= ~VG_MODEFLAG_INT_MASK;
+ panel_mode.flags |= (flags & VG_MODEFLAG_INT_MASK);
+ }
+
+ /* DYNAMICALLY CALCULATE CENTERED TIMINGS */
+ /* For centered timings the blank start and blank end are set to */
+ /* half the difference between the mode dimension and the panel */
+ /* dimension. The sync pulse preserves the width and offset from */
+ /* blanking whenever possible. */
+
+ if (dst_width < panel_width)
+ {
+ sync_width = panel_mode.hsyncend - panel_mode.hsyncstart;
+ sync_offset = panel_mode.hsyncstart - panel_mode.hblankstart;
+
+ panel_mode.hactive = dst_width;
+ panel_mode.hblankstart = panel_mode.hactive + ((panel_width - dst_width) >> 1);
+ panel_mode.hblankend = panel_mode.htotal - ((panel_width - dst_width) >> 1);
+ panel_mode.hsyncstart = panel_mode.hblankstart + sync_offset;
+ panel_mode.hsyncend = panel_mode.hsyncstart + sync_width;
+
+ panel_mode.flags |= VG_MODEFLAG_CENTERED;
+ }
+ if (dst_height < panel_height)
+ {
+ sync_width = panel_mode.vsyncend - panel_mode.vsyncstart;
+ sync_offset = panel_mode.vsyncstart - panel_mode.vblankstart;
+
+ panel_mode.vactive = dst_height;
+ panel_mode.vblankstart = panel_mode.vactive + ((panel_height - dst_height) >> 1);
+ panel_mode.vblankend = panel_mode.vtotal - ((panel_height - dst_height) >> 1);
+ panel_mode.vsyncstart = panel_mode.vblankstart + sync_offset;
+ panel_mode.vsyncend = panel_mode.vsyncstart + sync_width;
+
+ panel_mode.flags |= VG_MODEFLAG_CENTERED;
+ }
+ return vg_set_custom_mode (&panel_mode, bpp);
+ }
+ return CIM_STATUS_ERROR;
+}
+
+/*---------------------------------------------------------------------------
+ * vg_set_tv_mode
+ *
+ * This routine sets a TV display mode using predefined Cimarron timings. The
+ * source width and height are specified to allow scaling.
+ *---------------------------------------------------------------------------*/
+
+int vg_set_tv_mode (unsigned long *src_width, unsigned long *src_height,
+ unsigned long encoder, unsigned long tvres, int bpp, unsigned long flags,
+ unsigned long h_overscan, unsigned long v_overscan)
+{
+ unsigned long sync_width;
+ unsigned long sync_offset;
+ VG_QUERY_MODE tv_query;
+ VG_DISPLAY_MODE tv_mode;
+ int mode;
+
+ if (!src_width || !src_height)
+ return CIM_STATUS_INVALIDPARAMS;
+
+ tv_query.bpp = bpp;
+ tv_query.encoder = encoder;
+ tv_query.tvmode = tvres;
+ tv_query.query_flags = VG_QUERYFLAG_BPP |
+ VG_QUERYFLAG_TVOUT |
+ VG_QUERYFLAG_ENCODER |
+ VG_QUERYFLAG_TVMODE;
+
+ mode = vg_get_display_mode_index (&tv_query);
+ if (mode >= 0)
+ {
+ /* RETRIEVE THE UNSCALED RESOLUTION */
+ /* As we are indexing here simply by a mode and encoder, the actual */
+ /* timings may vary. A 0 value for source or height will thus query the */
+ /* unscaled resolution. */
+
+ if (!(*src_width) || !(*src_height))
+ {
+ *src_width = CimarronDisplayModes[mode].hactive - (h_overscan << 1);
+ *src_height = CimarronDisplayModes[mode].vactive;
+
+ if (CimarronDisplayModes[mode].flags & VG_MODEFLAG_INTERLACED)
+ {
+ if (((flags & VG_MODEFLAG_INT_OVERRIDE) &&
+ (flags & VG_MODEFLAG_INT_MASK) == VG_MODEFLAG_INT_LINEDOUBLE) ||
+ (!(flags & VG_MODEFLAG_INT_OVERRIDE) &&
+ (CimarronDisplayModes[mode].flags & VG_MODEFLAG_INT_MASK) == VG_MODEFLAG_INT_LINEDOUBLE))
+ {
+ if (CimarronDisplayModes[mode].vactive_even > CimarronDisplayModes[mode].vactive)
+ *src_height = CimarronDisplayModes[mode].vactive_even;
+
+ /* ONLY 1/2 THE OVERSCAN FOR LINE DOUBLED MODES */
+
+ *src_height -= v_overscan;
+ }
+ else
+ {
+ *src_height += CimarronDisplayModes[mode].vactive_even;
+ *src_height -= v_overscan << 1;
+ }
+ }
+ else
+ {
+ *src_height -= v_overscan << 1;
+ }
+
+ return CIM_STATUS_OK;
+ }
+
+ tv_mode = CimarronDisplayModes[mode];
+ tv_mode.src_width = *src_width;
+ tv_mode.src_height = *src_height;
+
+ /* ADD USER-REQUESTED FLAGS */
+
+ tv_mode.flags |= (flags & VG_MODEFLAG_VALIDUSERFLAGS);
+
+ if (flags & VG_MODEFLAG_OVERRIDE_BAND)
+ {
+ tv_mode.flags &= ~VG_MODEFLAG_BANDWIDTHMASK;
+ tv_mode.flags |= (flags & VG_MODEFLAG_BANDWIDTHMASK);
+ }
+ if (flags & VG_MODEFLAG_INT_OVERRIDE)
+ {
+ tv_mode.flags &= ~VG_MODEFLAG_INT_MASK;
+ tv_mode.flags |= (flags & VG_MODEFLAG_INT_MASK);
+ }
+
+ /* ADJUST FOR OVERSCAN */
+
+ if (h_overscan)
+ {
+ sync_width = tv_mode.hsyncend - tv_mode.hsyncstart;
+ sync_offset = tv_mode.hsyncstart - tv_mode.hblankstart;
+
+ tv_mode.hactive -= h_overscan << 1;
+ tv_mode.hblankstart = tv_mode.hactive + h_overscan;
+ tv_mode.hblankend = tv_mode.htotal - h_overscan;
+ tv_mode.hsyncstart = tv_mode.hblankstart + sync_offset;
+ tv_mode.hsyncend = tv_mode.hsyncstart + sync_width;
+
+ tv_mode.flags |= VG_MODEFLAG_CENTERED;
+ }
+ if (v_overscan)
+ {
+ sync_width = tv_mode.vsyncend - tv_mode.vsyncstart;
+ sync_offset = tv_mode.vsyncstart - tv_mode.vblankstart;
+
+ if (tv_mode.flags & VG_MODEFLAG_INTERLACED)
+ {
+ tv_mode.vactive -= v_overscan;
+ tv_mode.vblankstart = tv_mode.vactive + (v_overscan >> 1);
+ tv_mode.vblankend = tv_mode.vtotal - (v_overscan >> 1);
+ tv_mode.vsyncstart = tv_mode.vblankstart + sync_offset;
+ tv_mode.vsyncend = tv_mode.vsyncstart + sync_width;
+
+ sync_width = tv_mode.vsyncend_even - tv_mode.vsyncstart_even;
+ sync_offset = tv_mode.vsyncstart_even - tv_mode.vblankstart_even;
+
+ tv_mode.vactive_even -= v_overscan;
+ tv_mode.vblankstart_even = tv_mode.vactive_even + (v_overscan >> 1);
+ tv_mode.vblankend_even = tv_mode.vtotal_even - (v_overscan >> 1);
+ tv_mode.vsyncstart_even = tv_mode.vblankstart_even + sync_offset;
+ tv_mode.vsyncend_even = tv_mode.vsyncstart_even + sync_width;
+ }
+ else
+ {
+ tv_mode.vactive -= v_overscan << 1;
+ tv_mode.vblankstart = tv_mode.vactive + v_overscan;
+ tv_mode.vblankend = tv_mode.vtotal - v_overscan;
+ tv_mode.vsyncstart = tv_mode.vblankstart + sync_offset;
+ tv_mode.vsyncend = tv_mode.vsyncstart + sync_width;
+ }
+
+ tv_mode.flags |= VG_MODEFLAG_CENTERED;
+ }
+
+ /* TV MODES WILL NEVER ALLOW PANNING */
+
+ tv_mode.panel_width = tv_mode.hactive;
+ tv_mode.panel_height = tv_mode.vactive;
+ tv_mode.mode_width = tv_mode.hactive;
+ tv_mode.mode_height = tv_mode.vactive;
+
+ return vg_set_custom_mode (&tv_mode, bpp);
+ }
+ return CIM_STATUS_ERROR;
+}
+
+/*---------------------------------------------------------------------------
+ * vg_set_custom_mode
+ *
+ * This routine sets a display mode. The API is structured such that this routine
+ * can be called from four sources:
+ * - vg_set_display_mode
+ * - vg_set_panel_mode
+ * - vg_set_tv_mode
+ * - directly by the user for a custom mode.
+ *---------------------------------------------------------------------------*/
+
+int vg_set_custom_mode (VG_DISPLAY_MODE *mode_params, int bpp)
+{
+ unsigned long config, misc, temp;
+ unsigned long irq_ctl, genlk_ctl;
+ unsigned long unlock, flags;
+ unsigned long acfg, gcfg, dcfg;
+ unsigned long size, line_size, pitch;
+ unsigned long bpp_mask, dv_size;
+ unsigned long hscale, vscale, starting_width;
+ unsigned long starting_height, output_height;
+ Q_WORD msr_value;
+
+ /* DETERMINE DIMENSIONS FOR SCALING */
+ /* Scaling is performed before flicker filtering and interlacing */
+
+ output_height = mode_params->vactive;
+
+ if (mode_params->flags & VG_MODEFLAG_INTERLACED)
+ {
+ /* EVEN AND ODD FIELDS ARE SEPARATE */
+ /* The composite image height is the sum of the height of both fields */
+
+ if ((mode_params->flags & VG_MODEFLAG_INT_MASK) == VG_MODEFLAG_INT_FLICKER ||
+ (mode_params->flags & VG_MODEFLAG_INT_MASK) == VG_MODEFLAG_INT_ADDRESS)
+ {
+ output_height += mode_params->vactive_even;
+ }
+
+ /* LINE DOUBLING */
+ /* The composite image height is the greater of the two field heights. */
+
+ else if (mode_params->vactive_even > output_height)
+ output_height = mode_params->vactive_even;
+ }
+
+ /* CHECK FOR VALID SCALING FACTOR */
+ /* GeodeLX supports only 2:1 vertical downscale (before interlacing) and */
+ /* 2:1 horizontal downscale. The source width when scaling must be */
+ /* less than or equal to 1024 pixels. The destination can be any size, */
+ /* except when flicker filtering is enabled. */
+
+ irq_ctl = 0;
+ if (mode_params->flags & VG_MODEFLAG_PANELOUT)
+ {
+ if (mode_params->src_width != mode_params->mode_width)
+ {
+ starting_width = (mode_params->hactive * mode_params->src_width) / mode_params->mode_width;
+ hscale = (mode_params->src_width << 14) / (mode_params->mode_width - 1);
+ irq_ctl |= (DC3_IRQFILT_ALPHA_FILT_EN | DC3_IRQFILT_GFX_FILT_EN);
+ }
+ else
+ {
+ starting_width = mode_params->hactive;
+ hscale = 0x4000;
+ }
+ if (mode_params->src_height != mode_params->mode_height)
+ {
+ starting_height = (output_height * mode_params->src_height) / mode_params->mode_height;
+ vscale = (mode_params->src_height << 14) / (mode_params->mode_height - 1);
+ irq_ctl |= (DC3_IRQFILT_ALPHA_FILT_EN | DC3_IRQFILT_GFX_FILT_EN);
+ }
+ else
+ {
+ starting_height = output_height;
+ vscale = 0x4000;
+ }
+ }
+ else
+ {
+ starting_width = mode_params->src_width;
+ starting_height = mode_params->src_height;
+ if (mode_params->src_width != mode_params->hactive)
+ {
+ hscale = (mode_params->src_width << 14) / (mode_params->hactive - 1);
+ irq_ctl |= (DC3_IRQFILT_ALPHA_FILT_EN | DC3_IRQFILT_GFX_FILT_EN);
+ }
+ else
+ {
+ hscale = 0x4000;
+ }
+ if (mode_params->src_height != output_height)
+ {
+ vscale = (mode_params->src_height << 14) / (output_height - 1);
+ irq_ctl |= (DC3_IRQFILT_ALPHA_FILT_EN | DC3_IRQFILT_GFX_FILT_EN);
+ }
+ else
+ {
+ vscale = 0x4000;
+ }
+ }
+
+ starting_width = (starting_width + 7) & 0xFFFF8;
+
+ if (mode_params->hactive < (starting_width >> 1) ||
+ output_height < (starting_height >> 1) ||
+ (irq_ctl && (starting_width > 1024)))
+ {
+ return CIM_STATUS_INVALIDSCALE;
+ }
+
+ /* VERIFY INTERLACED SCALING */
+ /* The output width must be less than or equal to 1024 pixels when the */
+ /* flicker filter is enabled. Also, scaling should be disabled when */
+ /* the interlacing mode is set to interlaced addressing. */
+
+ if (mode_params->flags & VG_MODEFLAG_INTERLACED)
+ {
+ if ((((mode_params->flags & VG_MODEFLAG_INT_MASK) == VG_MODEFLAG_INT_FLICKER) &&
+ (mode_params->hactive > 1024)) ||
+ (((mode_params->flags & VG_MODEFLAG_INT_MASK) == VG_MODEFLAG_INT_ADDRESS) && irq_ctl))
+ {
+ return CIM_STATUS_INVALIDSCALE;
+ }
+ }
+
+ /* CHECK FOR VALID BPP */
+
+ switch (bpp)
+ {
+ case 8: bpp_mask = DC3_DCFG_DISP_MODE_8BPP; break;
+ case 24: bpp_mask = DC3_DCFG_DISP_MODE_24BPP; break;
+ case 32: bpp_mask = DC3_DCFG_DISP_MODE_32BPP; break;
+ case 12: bpp_mask = DC3_DCFG_DISP_MODE_16BPP | DC3_DCFG_12BPP; break;
+ case 15: bpp_mask = DC3_DCFG_DISP_MODE_16BPP | DC3_DCFG_15BPP; break;
+ case 16: bpp_mask = DC3_DCFG_DISP_MODE_16BPP | DC3_DCFG_16BPP; break;
+ default: return CIM_STATUS_INVALIDPARAMS;
+ }
+
+ vg3_bpp = bpp;
+
+ /* CLEAR PANNING OFFSETS */
+
+ vg3_delta_x = 0;
+ vg3_delta_y = 0;
+
+ /* SAVE PANEL PARAMETERS */
+
+ if (mode_params->flags & VG_MODEFLAG_PANELOUT)
+ {
+ vg3_panel_enable = 1;
+ vg3_panel_width = mode_params->panel_width;
+ vg3_panel_height = mode_params->panel_height;
+ vg3_mode_width = mode_params->mode_width;
+ vg3_mode_height = mode_params->mode_height;
+
+ /* INVERT THE SHIFT CLOCK IF REQUESTED */
+ /* Note that we avoid writing the power management register if */
+ /* we can help it. */
+
+ temp = READ_VID32 (DF_POWER_MANAGEMENT);
+ if ((mode_params->flags & VG_MODEFLAG_INVERT_SHFCLK) &&
+ !(temp & DF_PM_INVERT_SHFCLK))
+ {
+ WRITE_VID32 (DF_POWER_MANAGEMENT, (temp | DF_PM_INVERT_SHFCLK));
+ }
+ else if (!(mode_params->flags & VG_MODEFLAG_INVERT_SHFCLK) &&
+ (temp & DF_PM_INVERT_SHFCLK))
+ {
+ WRITE_VID32 (DF_POWER_MANAGEMENT, (temp & ~DF_PM_INVERT_SHFCLK));
+ }
+
+ /* SET PANEL TIMING VALUES */
+
+ if (!(mode_params->flags & VG_MODEFLAG_NOPANELTIMINGS))
+ {
+ unsigned long pmtim1, pmtim2, dith_ctl;
+
+ if (mode_params->flags & VG_MODEFLAG_XVGA_TFT)
+ {
+ pmtim1 = DF_DEFAULT_XVGA_PMTIM1;
+ pmtim2 = DF_DEFAULT_XVGA_PMTIM2;
+ dith_ctl = DF_DEFAULT_DITHCTL;
+ msr_value.low = DF_DEFAULT_XVGA_PAD_SEL_LOW;
+ msr_value.high = DF_DEFAULT_XVGA_PAD_SEL_HIGH;
+ }
+ else if (mode_params->flags & VG_MODEFLAG_CUSTOM_PANEL)
+ {
+ pmtim1 = mode_params->panel_tim1;
+ pmtim2 = mode_params->panel_tim2;
+ dith_ctl = mode_params->panel_dither_ctl;
+ msr_value.low = mode_params->panel_pad_sel_low;
+ msr_value.high = mode_params->panel_pad_sel_high;
+ }
+ else
+ {
+ pmtim1 = DF_DEFAULT_TFT_PMTIM1;
+ pmtim2 = DF_DEFAULT_TFT_PMTIM2;
+ dith_ctl = DF_DEFAULT_DITHCTL;
+ msr_value.low = DF_DEFAULT_TFT_PAD_SEL_LOW;
+ msr_value.high = DF_DEFAULT_TFT_PAD_SEL_HIGH;
+
+ }
+ WRITE_VID32 (DF_VIDEO_PANEL_TIM1, pmtim1);
+ WRITE_VID32 (DF_VIDEO_PANEL_TIM2, pmtim2);
+ WRITE_VID32 (DF_DITHER_CONTROL, dith_ctl);
+ msr_write64 (MSR_DEVICE_GEODELX_DF, DF_MSR_PAD_SEL, &msr_value);
+ }
+
+ /* SET APPROPRIATE PANEL OUTPUT MODE */
+
+ msr_read64 (MSR_DEVICE_GEODELX_DF, MSR_GEODELINK_CONFIG, &msr_value);
+
+ msr_value.low &= ~DF_CONFIG_OUTPUT_MASK;
+ msr_value.low |= DF_OUTPUT_PANEL;
+ if (mode_params->flags & VG_MODEFLAG_CRT_AND_FP)
+ msr_value.low |= DF_SIMULTANEOUS_CRT_FP;
+ else
+ msr_value.low &= ~DF_SIMULTANEOUS_CRT_FP;
+
+ msr_write64 (MSR_DEVICE_GEODELX_DF, MSR_GEODELINK_CONFIG, &msr_value);
+
+ }
+ else if (mode_params->flags & VG_MODEFLAG_TVOUT)
+ {
+ vg3_panel_enable = 0;
+
+ /* SET APPROPRIATE TV OUTPUT MODE */
+
+ msr_read64 (MSR_DEVICE_GEODELX_DF, MSR_GEODELINK_CONFIG, &msr_value);
+
+ msr_value.low &= ~DF_CONFIG_OUTPUT_MASK;
+ msr_value.low |= DF_OUTPUT_PANEL;
+ if (mode_params->flags & VG_MODEFLAG_CRT_AND_FP)
+ msr_value.low |= DF_SIMULTANEOUS_CRT_FP;
+ else
+ msr_value.low &= ~DF_SIMULTANEOUS_CRT_FP;
+
+ msr_write64 (MSR_DEVICE_GEODELX_DF, MSR_GEODELINK_CONFIG, &msr_value);
+
+ /* CONFIGURE PADS FOR VOP OUTPUT */
+ /* Note that the VOP clock is currently always inverted. */
+
+ msr_value.low = DF_DEFAULT_TV_PAD_SEL_LOW;
+ msr_value.high = DF_DEFAULT_TV_PAD_SEL_HIGH;
+ msr_write64 (MSR_DEVICE_GEODELX_DF, DF_MSR_PAD_SEL, &msr_value);
+ }
+ else
+ {
+ vg3_panel_enable = 0;
+
+ /* SET OUTPUT TO CRT ONLY */
+
+ msr_read64 (MSR_DEVICE_GEODELX_DF, MSR_GEODELINK_CONFIG, &msr_value);
+ msr_value.low &= ~DF_CONFIG_OUTPUT_MASK;
+ msr_value.low |= DF_OUTPUT_CRT;
+ msr_write64 (MSR_DEVICE_GEODELX_DF, MSR_GEODELINK_CONFIG, &msr_value);
+ }
+
+ /* SET UNLOCK VALUE */
+
+ unlock = READ_REG32 (DC3_UNLOCK);
+ WRITE_REG32 (DC3_UNLOCK, DC3_UNLOCK_VALUE);
+
+ /*-------------------------------------------------------------------*/
+ /* MAKE THE SYSTEM "SAFE" */
+ /* Before setting a mode, we first ensure that the system is in a */
+ /* benign quiescent state. This involves disabling compression and */
+ /* all interrupt sources. It also involves terminating all accesses */
+ /* to memory, including video, FIFO load, VIP and the GP. */
+ /*-------------------------------------------------------------------*/
+
+ /* DISABLE VGA */
+ /* VGA *MUST* be turned off before TGEN is enabled. If not, a condition */
+ /* will result where VGA Enable is waiting for a VSync to be latched but */
+ /* a VSync will not be generated until VGA is disabled. */
+
+ temp = READ_REG32 (DC3_GENERAL_CFG) & ~DC3_GCFG_VGAE;
+
+ /* DISABLE VIDEO (INCLUDING ALPHA WINDOWS) */
+
+ WRITE_VID32 (DF_ALPHA_CONTROL_1, 0);
+ WRITE_VID32 (DF_ALPHA_CONTROL_1 + 32, 0);
+ WRITE_VID32 (DF_ALPHA_CONTROL_1 + 64, 0);
+
+ WRITE_REG32 (DC3_GENERAL_CFG, (temp & ~DC3_GCFG_VIDE));
+ temp = READ_VID32 (DF_VIDEO_CONFIG);
+ WRITE_VID32 (DF_VIDEO_CONFIG, (temp & ~DF_VCFG_VID_EN));
+
+ /* DISABLE VG INTERRUPTS */
+
+ WRITE_REG32 (DC3_IRQ, DC3_IRQ_MASK | DC3_VSYNC_IRQ_MASK |
+ DC3_IRQ_STATUS | DC3_VSYNC_IRQ_STATUS);
+
+ /* DISABLE GENLOCK */
+
+ genlk_ctl = READ_REG32 (DC3_GENLK_CTL);
+ WRITE_REG32 (DC3_GENLK_CTL, (genlk_ctl & ~DC3_GC_GENLOCK_ENABLE));
+
+ /* DISABLE VIP CAPTURE AND VIP INTERRUPTS */
+
+ WRITE_VIP32 (VIP_CONTROL1, 0);
+ WRITE_VIP32 (VIP_CONTROL2, 0);
+ WRITE_VIP32 (VIP_INTERRUPT, VIP_ALL_INTERRUPTS | (VIP_ALL_INTERRUPTS >> 16));
+
+ /* DISABLE COLOR KEYING */
+ /* The color key mechanism should be disabled whenever a mode switch occurs. */
+
+ temp = READ_REG32 (DC3_COLOR_KEY);
+ WRITE_REG32 (DC3_COLOR_KEY, (temp & ~DC3_CLR_KEY_ENABLE));
+
+ /* BLANK THE DISPLAY */
+ /* Note that we never blank the panel. Most flat panels have very long */
+ /* latency requirements when setting their power low. Some panels require */
+ /* upwards of 500ms before VDD goes high again. Needless to say, we are not */
+ /* planning to take over one half a second inside this routine. */
+
+ misc = READ_VID32 (DF_VID_MISC);
+ config = READ_VID32 (DF_DISPLAY_CONFIG);
+
+ WRITE_VID32 (DF_VID_MISC, (misc | DF_DAC_POWER_DOWN));
+ WRITE_VID32 (DF_DISPLAY_CONFIG, (config & ~(DF_DCFG_DIS_EN | DF_DCFG_HSYNC_EN |
+ DF_DCFG_VSYNC_EN | DF_DCFG_DAC_BL_EN)));
+
+ /* DISABLE COMPRESSION */
+
+ gcfg = READ_REG32 (DC3_GENERAL_CFG);
+ gcfg &= ~(DC3_GCFG_CMPE | DC3_GCFG_DECE);
+ WRITE_REG32 (DC3_GENERAL_CFG, gcfg);
+
+ /* DISABLE THE TIMING GENERATOR */
+
+ dcfg = READ_REG32 (DC3_DISPLAY_CFG);
+ dcfg &= ~DC3_DCFG_TGEN;
+ WRITE_REG32 (DC3_DISPLAY_CFG, dcfg);
+
+ /* WAIT FOR PENDING MEMORY REQUESTS */
+
+ vg_delay_milliseconds(1);
+
+ /* DISABLE DISPLAY FIFO LOAD */
+
+ gcfg &= ~DC3_GCFG_DFLE;
+ WRITE_REG32 (DC3_GENERAL_CFG, gcfg);
+ gcfg = 0;
+ dcfg = 0;
+
+ /* WAIT FOR THE GP TO BE IDLE (JUST IN CASE) */
+
+ while (((temp = READ_GP32 (GP3_BLT_STATUS)) & GP3_BS_BLT_BUSY) ||
+ !(temp & GP3_BS_CB_EMPTY))
+ {
+ ;
+ }
+
+ /* SET THE DOT CLOCK FREQUENCY */
+
+ if (!(mode_params->flags & VG_MODEFLAG_EXCLUDEPLL))
+ {
+ if (mode_params->flags & VG_MODEFLAG_HALFCLOCK)
+ flags = VG_PLL_DIVIDE_BY_2;
+ else if (mode_params->flags & VG_MODEFLAG_QVGA)
+ flags = VG_PLL_DIVIDE_BY_4;
+ else
+ flags = 0;
+
+ /* ALLOW DOTREF TO BE USED AS THE PLL */
+ /* This is useful for some external TV encoders. */
+
+ if (mode_params->flags & VG_MODEFLAG_PLL_BYPASS)
+ flags |= VG_PLL_BYPASS;
+
+ /* ALLOW THE USER TO MANUALLY ENTER THE MSR VALUE */
+
+ if (mode_params->flags & VG_MODEFLAG_MANUAL_FREQUENCY)
+ flags |= VG_PLL_MANUAL;
+ if (mode_params->flags & VG_MODEFLAG_VIP_TO_DOT_CLOCK)
+ flags |= VG_PLL_VIP_CLOCK;
+
+ vg_set_clock_frequency (mode_params->frequency, flags);
+ }
+
+ /* CLEAR ALL BUFFER OFFSETS */
+
+ WRITE_REG32 (DC3_FB_ST_OFFSET, 0);
+ WRITE_REG32 (DC3_CB_ST_OFFSET, 0);
+ WRITE_REG32 (DC3_CURS_ST_OFFSET, 0);
+
+ genlk_ctl = READ_REG32 (DC3_GENLK_CTL) & ~(DC3_GC_ALPHA_FLICK_ENABLE |
+ DC3_GC_FLICKER_FILTER_ENABLE | DC3_GC_FLICKER_FILTER_MASK);
+
+ /* ENABLE INTERLACING */
+
+ if (mode_params->flags & VG_MODEFLAG_INTERLACED)
+ {
+ irq_ctl |= DC3_IRQFILT_INTL_EN;
+
+ if ((mode_params->flags & VG_MODEFLAG_INT_MASK) == VG_MODEFLAG_INT_ADDRESS)
+ irq_ctl |= DC3_IRQFILT_INTL_ADDR;
+ else if ((mode_params->flags & VG_MODEFLAG_INT_MASK) == VG_MODEFLAG_INT_FLICKER)
+ {
+ genlk_ctl |= DC3_GC_FLICKER_FILTER_1_8 | DC3_GC_FLICKER_FILTER_ENABLE |
+ DC3_GC_ALPHA_FLICK_ENABLE;
+ }
+ }
+
+ WRITE_REG32 (DC3_GFX_SCALE, (vscale << 16) | (hscale & 0xFFFF));
+ WRITE_REG32 (DC3_IRQ_FILT_CTL, irq_ctl);
+ WRITE_REG32 (DC3_GENLK_CTL, genlk_ctl);
+
+ /* SET LINE SIZE AND PITCH */
+ /* The line size and pitch are calculated from the src_width parameter */
+ /* passed in to this routine. All other parameters are ignored. */
+ /* The pitch is set either to a power of 2 to allow efficient */
+ /* compression or to a linear value to allow efficient memory management. */
+
+ switch (bpp)
+ {
+ case 8:
+ size = mode_params->src_width;
+ line_size = starting_width;
+ break;
+
+ case 12:
+ case 15:
+ case 16:
+
+ size = mode_params->src_width << 1;
+ line_size = starting_width << 1;
+ break;
+
+ case 24:
+ case 32:
+ default:
+
+ size = mode_params->src_width << 2;
+ line_size = starting_width << 2; break;
+ }
+
+ /* CALCULATE DV RAM SETTINGS AND POWER OF 2 PITCH */
+
+ pitch = 1024;
+ dv_size = DC3_DV_LINE_SIZE_1024;
+
+ if (size > 1024) { pitch = 2048; dv_size = DC3_DV_LINE_SIZE_2048; }
+ if (size > 2048) { pitch = 4096; dv_size = DC3_DV_LINE_SIZE_4096; }
+ if (size > 4096) { pitch = 8192; dv_size = DC3_DV_LINE_SIZE_8192; }
+
+ /* OVERRIDE SETTINGS FOR LINEAR PITCH */
+
+ if (mode_params->flags & VG_MODEFLAG_LINEARPITCH)
+ {
+ unsigned long max;
+ if (pitch != size)
+ {
+ /* CALCULATE MAXIMUM ADDRESS (1K ALIGNED) */
+
+ max = size * output_height;
+ max = (max + 0x3FF) & 0xFFFFFC00;
+ WRITE_REG32 (DC3_DV_TOP, max | DC3_DVTOP_ENABLE);
+
+ gcfg |= DC3_GCFG_FDTY;
+ pitch = size;
+ }
+ else
+ {
+ WRITE_REG32 (DC3_DV_TOP, 0);
+ }
+ }
+
+ /* WRITE PITCH AND DV RAM SETTINGS */
+ /* The DV RAM line length is programmed at a power of 2 boundary */
+ /* in case the user wants to toggle back to a power of 2 pitch */
+ /* later. It could happen... */
+
+ temp = READ_REG32 (DC3_DV_CTL);
+ WRITE_REG32 (DC3_GFX_PITCH, pitch >> 3);
+ WRITE_REG32 (DC3_DV_CTL, (temp & ~DC3_DV_LINE_SIZE_MASK) | dv_size);
+
+ /* SET THE LINE SIZE */
+
+ WRITE_REG32 (DC3_LINE_SIZE, (line_size + 7) >> 3);
+
+ /* ALWAYS ENABLE VIDEO AND GRAPHICS DATA */
+ /* These bits are relics from a previous design and */
+ /* should always be enabled. */
+
+ dcfg |= (DC3_DCFG_VDEN | DC3_DCFG_GDEN);
+
+ /* SET PIXEL FORMAT */
+
+ dcfg |= bpp_mask;
+
+ /* ENABLE TIMING GENERATOR, TIM. REG. UPDATES, PALETTE BYPASS */
+ /* AND VERT. INT. SELECT */
+
+ dcfg |= (unsigned long)(DC3_DCFG_TGEN | DC3_DCFG_TRUP | DC3_DCFG_PALB | DC3_DCFG_VISL);
+
+ /* SET FIFO PRIORITIES AND DISPLAY FIFO LOAD ENABLE */
+ /* Note that the bandwidth setting gets upgraded when scaling or flicker */
+ /* filtering are enabled, as they require more data throughput. */
+
+ msr_read64 (MSR_DEVICE_GEODELX_VG, DC3_SPARE_MSR, &msr_value);
+ msr_value.low &= ~(DC3_SPARE_DISABLE_CFIFO_HGO | DC3_SPARE_VFIFO_ARB_SELECT |
+ DC3_SPARE_LOAD_WM_LPEN_MASK | DC3_SPARE_WM_LPEN_OVRD |
+ DC3_SPARE_DISABLE_INIT_VID_PRI | DC3_SPARE_DISABLE_VFIFO_WM);
+
+ if ((mode_params->flags & VG_MODEFLAG_BANDWIDTHMASK) == VG_MODEFLAG_HIGH_BAND ||
+ ((mode_params->flags & VG_MODEFLAG_INTERLACED) &&
+ (mode_params->flags & VG_MODEFLAG_INT_MASK) == VG_MODEFLAG_INT_FLICKER) ||
+ (irq_ctl & DC3_IRQFILT_GFX_FILT_EN))
+ {
+ /* HIGH BANDWIDTH */
+ /* Set agressive watermarks and disallow forced low priority */
+
+ gcfg |= 0x0000BA01;
+ dcfg |= 0x000EA000;
+ acfg = 0x001A0201;
+
+ msr_value.low |= DC3_SPARE_DISABLE_CFIFO_HGO | DC3_SPARE_VFIFO_ARB_SELECT |
+ DC3_SPARE_WM_LPEN_OVRD;
+ }
+ else if ((mode_params->flags & VG_MODEFLAG_BANDWIDTHMASK) == VG_MODEFLAG_AVG_BAND)
+ {
+ /* AVERAGE BANDWIDTH */
+ /* Set average watermarks and allow small regions of forced low priority. */
+
+ gcfg |= 0x0000B601;
+ dcfg |= 0x00009000;
+ acfg = 0x00160001;
+
+ msr_value.low |= DC3_SPARE_DISABLE_CFIFO_HGO | DC3_SPARE_VFIFO_ARB_SELECT |
+ DC3_SPARE_WM_LPEN_OVRD;
+
+ /* SET THE NUMBER OF LOW PRIORITY LINES TO 1/2 THE TOTAL AVAILABLE */
+
+ temp = ((READ_REG32 (DC3_V_ACTIVE_TIMING) >> 16) & 0x7FF) + 1;
+ temp -= (READ_REG32 (DC3_V_SYNC_TIMING) & 0x7FF) + 1;
+ temp >>= 1;
+ if (temp > 127)
+ temp = 127;
+
+ acfg |= temp << 9;
+ }
+ else if ((mode_params->flags & VG_MODEFLAG_BANDWIDTHMASK) == VG_MODEFLAG_LOW_BAND)
+ {
+ /* LOW BANDWIDTH */
+ /* Set low watermarks and allow larger regions of forced low priority. */
+
+ gcfg |= 0x00009501;
+ dcfg |= 0x00008000;
+ acfg = 0x00150001;
+
+ msr_value.low |= DC3_SPARE_DISABLE_CFIFO_HGO | DC3_SPARE_VFIFO_ARB_SELECT |
+ DC3_SPARE_WM_LPEN_OVRD;
+
+ /* SET THE NUMBER OF LOW PRIORITY LINES TO 3/4 THE TOTAL AVAILABLE */
+
+ temp = ((READ_REG32 (DC3_V_ACTIVE_TIMING) >> 16) & 0x7FF) + 1;
+ temp -= (READ_REG32 (DC3_V_SYNC_TIMING) & 0x7FF) + 1;
+ temp = (temp * 3) >> 2;
+ if (temp > 127)
+ temp = 127;
+
+ acfg |= temp << 9;
+ }
+ else
+ {
+ /* LEGACY CHARACTERISTICS */
+ /* Arbitration from a single set of watermarks. */
+
+ gcfg |= 0x0000B601;
+ msr_value.low |= DC3_SPARE_DISABLE_VFIFO_WM | DC3_SPARE_DISABLE_INIT_VID_PRI;
+ acfg = 0;
+ }
+
+ msr_write64 (MSR_DEVICE_GEODELX_VG, DC3_SPARE_MSR, &msr_value);
+
+ /* ENABLE FLAT PANEL CENTERING */
+ /* For panel modes having a resolution smaller than the */
+ /* panel resolution, turn on data centering. */
+
+ if (mode_params->flags & VG_MODEFLAG_CENTERED)
+ dcfg |= DC3_DCFG_DCEN;
+
+ /* COMBINE AND SET TIMING VALUES */
+
+ temp = (mode_params->hactive - 1) | ((mode_params->htotal - 1) << 16);
+ WRITE_REG32(DC3_H_ACTIVE_TIMING, temp);
+ temp = (mode_params->hblankstart - 1) | ((mode_params->hblankend - 1) << 16);
+ WRITE_REG32(DC3_H_BLANK_TIMING, temp);
+ temp = (mode_params->hsyncstart - 1) | ((mode_params->hsyncend - 1) << 16);
+ WRITE_REG32(DC3_H_SYNC_TIMING, temp);
+ temp = (mode_params->vactive - 1) | ((mode_params->vtotal - 1) << 16);
+ WRITE_REG32(DC3_V_ACTIVE_TIMING, temp);
+ temp = (mode_params->vblankstart - 1) | ((mode_params->vblankend - 1) << 16);
+ WRITE_REG32(DC3_V_BLANK_TIMING, temp);
+ temp = (mode_params->vsyncstart - 1) | ((mode_params->vsyncend - 1) << 16);
+ WRITE_REG32(DC3_V_SYNC_TIMING, temp);
+ temp = (mode_params->vactive_even - 1) | ((mode_params->vtotal_even - 1) << 16);
+ WRITE_REG32(DC3_V_ACTIVE_EVEN, temp);
+ temp = (mode_params->vblankstart_even - 1) | ((mode_params->vblankend_even - 1) << 16);
+ WRITE_REG32(DC3_V_BLANK_EVEN, temp);
+ temp = (mode_params->vsyncstart_even - 1) | ((mode_params->vsyncend_even - 1) << 16);
+ WRITE_REG32(DC3_V_SYNC_EVEN, temp);
+
+ /* SET THE VIDEO REQUEST REGISTER */
+
+ WRITE_VID32 (DF_VIDEO_REQUEST, 0);
+
+ /* SET SOURCE DIMENSIONS */
+
+ WRITE_REG32 (DC3_FB_ACTIVE, ((starting_width - 1) << 16) |
+ (starting_height - 1));
+
+ /* SET SYNC POLARITIES */
+
+ temp = READ_VID32 (DF_DISPLAY_CONFIG);
+
+ temp &= ~(DF_DCFG_CRT_SYNC_SKW_MASK | DF_DCFG_PWR_SEQ_DLY_MASK |
+ DF_DCFG_CRT_HSYNC_POL | DF_DCFG_CRT_VSYNC_POL);
+
+ temp |= (DF_DCFG_CRT_SYNC_SKW_INIT |
+ DF_DCFG_PWR_SEQ_DLY_INIT |
+ DF_DCFG_GV_PAL_BYP);
+
+ if (mode_params->flags & VG_MODEFLAG_NEG_HSYNC)
+ temp |= DF_DCFG_CRT_HSYNC_POL;
+ if (mode_params->flags & VG_MODEFLAG_NEG_VSYNC)
+ temp |= DF_DCFG_CRT_VSYNC_POL;
+
+ WRITE_VID32 (DF_DISPLAY_CONFIG, temp);
+
+ WRITE_REG32 (DC3_DISPLAY_CFG, dcfg);
+ WRITE_REG32 (DC3_ARB_CFG, acfg);
+ WRITE_REG32 (DC3_GENERAL_CFG, gcfg);
+
+ /* RESTORE VALUE OF DC3_UNLOCK */
+
+ WRITE_REG32(DC3_UNLOCK, unlock);
+
+ return CIM_STATUS_OK;
+}
+
+/*---------------------------------------------------------------------------
+ * vg_set_bpp
+ *
+ * This routine changes the display BPP on the fly. It is intended only to
+ * switch between pixel depths of the same pixel size 24<->32 or 15<->16, NOT
+ * between pixel depths of differing sizes 16<->32
+ *---------------------------------------------------------------------------*/
+
+int vg_set_display_bpp (int bpp)
+{
+ unsigned long unlock, dcfg, bpp_mask;
+
+ switch (bpp)
+ {
+ case 8: bpp_mask = DC3_DCFG_DISP_MODE_8BPP; break;
+ case 24: bpp_mask = DC3_DCFG_DISP_MODE_24BPP; break;
+ case 32: bpp_mask = DC3_DCFG_DISP_MODE_32BPP; break;
+ case 12: bpp_mask = DC3_DCFG_DISP_MODE_16BPP | DC3_DCFG_12BPP; break;
+ case 15: bpp_mask = DC3_DCFG_DISP_MODE_16BPP | DC3_DCFG_15BPP; break;
+ case 16: bpp_mask = DC3_DCFG_DISP_MODE_16BPP | DC3_DCFG_16BPP; break;
+ default: return CIM_STATUS_INVALIDPARAMS;
+ }
+
+ unlock = READ_REG32 (DC3_UNLOCK);
+ dcfg = READ_REG32 (DC3_DISPLAY_CFG) & ~(DC3_DCFG_DISP_MODE_MASK | DC3_DCFG_16BPP_MODE_MASK);
+ dcfg |= bpp_mask;
+
+ WRITE_REG32 (DC3_UNLOCK, DC3_UNLOCK_VALUE);
+ WRITE_REG32 (DC3_DISPLAY_CFG, dcfg);
+ WRITE_REG32 (DC3_UNLOCK, unlock);
+
+ return CIM_STATUS_OK;
+}
+
+/*---------------------------------------------------------------------------
+ * vg_get_display_mode_index
+ *
+ * This routine searches the Cimarron mode table for a mode that matches the
+ * input parameters. If a match is found, the return value is the index into
+ * the mode table. If no match is found, the return value is -1.
+ *---------------------------------------------------------------------------*/
+
+int vg_get_display_mode_index (VG_QUERY_MODE *query)
+{
+ unsigned int mode;
+ unsigned long hz_flag = 0xFFFFFFFF;
+ unsigned long bpp_flag = 0xFFFFFFFF;
+ unsigned long enc_flag = 0xFFFFFFFF;
+ unsigned long tv_flag = 0;
+ unsigned long interlaced = 0;
+ unsigned long halfclock = 0;
+ long minimum = 0x7FFFFFFF;
+ long diff;
+ int match = -1;
+
+ if (!query || !query->query_flags)
+ return -1;
+
+ if (query->query_flags & VG_QUERYFLAG_REFRESH)
+ {
+ /* SET FLAGS TO MATCH REFRESH RATE */
+
+ if (query->hz == 56) hz_flag = VG_SUPPORTFLAG_56HZ;
+ else if (query->hz == 60) hz_flag = VG_SUPPORTFLAG_60HZ;
+ else if (query->hz == 70) hz_flag = VG_SUPPORTFLAG_70HZ;
+ else if (query->hz == 72) hz_flag = VG_SUPPORTFLAG_72HZ;
+ else if (query->hz == 75) hz_flag = VG_SUPPORTFLAG_75HZ;
+ else if (query->hz == 85) hz_flag = VG_SUPPORTFLAG_85HZ;
+ else if (query->hz == 90) hz_flag = VG_SUPPORTFLAG_90HZ;
+ else if (query->hz == 100) hz_flag = VG_SUPPORTFLAG_100HZ;
+ else hz_flag = 0;
+ }
+
+ if (query->query_flags & VG_QUERYFLAG_BPP)
+ {
+ /* SET BPP FLAGS TO LIMIT MODE SELECTION */
+
+ if (query->bpp == 8) bpp_flag = VG_SUPPORTFLAG_8BPP;
+ else if (query->bpp == 12) bpp_flag = VG_SUPPORTFLAG_12BPP;
+ else if (query->bpp == 15) bpp_flag = VG_SUPPORTFLAG_15BPP;
+ else if (query->bpp == 16) bpp_flag = VG_SUPPORTFLAG_16BPP;
+ else if (query->bpp == 24) bpp_flag = VG_SUPPORTFLAG_24BPP;
+ else if (query->bpp == 32) bpp_flag = VG_SUPPORTFLAG_32BPP;
+ else bpp_flag = 0;
+ }
+
+ if (query->query_flags & VG_QUERYFLAG_ENCODER)
+ {
+ /* SET ENCODER FLAGS TO LIMIT MODE SELECTION */
+
+ if (query->encoder == VG_ENCODER_ADV7171) enc_flag = VG_SUPPORTFLAG_ADV7171;
+ else if (query->encoder == VG_ENCODER_SAA7127) enc_flag = VG_SUPPORTFLAG_SAA7127;
+ else if (query->encoder == VG_ENCODER_FS454) enc_flag = VG_SUPPORTFLAG_FS454;
+ else if (query->encoder == VG_ENCODER_ADV7300) enc_flag = VG_SUPPORTFLAG_ADV7300;
+ else enc_flag = 0;
+ }
+
+ if (query->query_flags & VG_QUERYFLAG_TVMODE)
+ {
+ /* SET ENCODER FLAGS TO LIMIT MODE SELECTION */
+
+ if (query->tvmode == VG_TVMODE_NTSC) tv_flag = VG_SUPPORTFLAG_NTSC;
+ else if (query->tvmode == VG_TVMODE_PAL) tv_flag = VG_SUPPORTFLAG_PAL;
+ else if (query->tvmode == VG_TVMODE_480P) tv_flag = VG_SUPPORTFLAG_480P;
+ else if (query->tvmode == VG_TVMODE_720P) tv_flag = VG_SUPPORTFLAG_720P;
+ else if (query->tvmode == VG_TVMODE_1080I) tv_flag = VG_SUPPORTFLAG_1080I;
+ else if (query->tvmode == VG_TVMODE_6X4_NTSC) tv_flag = VG_SUPPORTFLAG_6X4_NTSC;
+ else if (query->tvmode == VG_TVMODE_8X6_NTSC) tv_flag = VG_SUPPORTFLAG_8X6_NTSC;
+ else if (query->tvmode == VG_TVMODE_10X7_NTSC) tv_flag = VG_SUPPORTFLAG_10X7_NTSC;
+ else if (query->tvmode == VG_TVMODE_6X4_PAL) tv_flag = VG_SUPPORTFLAG_6X4_PAL;
+ else if (query->tvmode == VG_TVMODE_8X6_PAL) tv_flag = VG_SUPPORTFLAG_8X6_PAL;
+ else if (query->tvmode == VG_TVMODE_10X7_PAL) tv_flag = VG_SUPPORTFLAG_10X7_PAL;
+ else tv_flag = 0xFFFFFFFF;
+ }
+
+ /* SET APPROPRIATE TV AND VOP FLAGS */
+
+ if (query->query_flags & VG_QUERYFLAG_INTERLACED)
+ interlaced = query->interlaced ? VG_MODEFLAG_INTERLACED : 0;
+ if (query->query_flags & VG_QUERYFLAG_HALFCLOCK)
+ halfclock = query->halfclock ? VG_MODEFLAG_HALFCLOCK : 0;
+
+ /* CHECK FOR INVALID REQUEST */
+
+ if (!hz_flag || !bpp_flag || !enc_flag || tv_flag == 0xFFFFFFFF)
+ return -1;
+
+ /* LOOP THROUGH THE AVAILABLE MODES TO FIND A MATCH */
+
+ for (mode = 0; mode < NUM_CIMARRON_DISPLAY_MODES; mode++)
+ {
+ if ( (!(query->query_flags & VG_QUERYFLAG_PANEL) ||
+ (CimarronDisplayModes[mode].internal_flags & VG_SUPPORTFLAG_PANEL)) &&
+ (!(query->query_flags & VG_QUERYFLAG_TVOUT) ||
+ (CimarronDisplayModes[mode].internal_flags & VG_SUPPORTFLAG_TVOUT)) &&
+ (!(query->query_flags & VG_QUERYFLAG_INTERLACED) ||
+ (CimarronDisplayModes[mode].flags & VG_MODEFLAG_INTERLACED) == interlaced) &&
+ (!(query->query_flags & VG_QUERYFLAG_HALFCLOCK) ||
+ (CimarronDisplayModes[mode].flags & VG_MODEFLAG_HALFCLOCK) == halfclock) &&
+ (!(query->query_flags & VG_QUERYFLAG_PANELWIDTH) ||
+ (CimarronDisplayModes[mode].panel_width == query->panel_width)) &&
+ (!(query->query_flags & VG_QUERYFLAG_PANELHEIGHT) ||
+ (CimarronDisplayModes[mode].panel_height == query->panel_height)) &&
+ (!(query->query_flags & VG_QUERYFLAG_ACTIVEWIDTH) ||
+ (CimarronDisplayModes[mode].hactive == query->active_width)) &&
+ (!(query->query_flags & VG_QUERYFLAG_ACTIVEHEIGHT) ||
+ (CimarronDisplayModes[mode].vactive == query->active_height)) &&
+ (!(query->query_flags & VG_QUERYFLAG_TOTALWIDTH) ||
+ (CimarronDisplayModes[mode].htotal == query->total_width)) &&
+ (!(query->query_flags & VG_QUERYFLAG_TOTALHEIGHT) ||
+ (CimarronDisplayModes[mode].vtotal == query->total_height)) &&
+ (!(query->query_flags & VG_QUERYFLAG_BPP) ||
+ (CimarronDisplayModes[mode].internal_flags & bpp_flag)) &&
+ (!(query->query_flags & VG_QUERYFLAG_REFRESH) ||
+ (CimarronDisplayModes[mode].internal_flags & hz_flag)) &&
+ (!(query->query_flags & VG_QUERYFLAG_ENCODER) ||
+ (CimarronDisplayModes[mode].internal_flags & enc_flag)) &&
+ (!(query->query_flags & VG_QUERYFLAG_TVMODE) ||
+ ((CimarronDisplayModes[mode].internal_flags & VG_SUPPORTFLAG_TVMODEMASK) == tv_flag)) &&
+ (!(query->query_flags & VG_QUERYFLAG_PIXELCLOCK) ||
+ (CimarronDisplayModes[mode].frequency == query->frequency)))
+ {
+ /* ALLOW SEARCHING BASED ON AN APPROXIMATE PIXEL CLOCK */
+
+ if (query->query_flags & VG_QUERYFLAG_PIXELCLOCK_APPROX)
+ {
+ diff = query->frequency - CimarronDisplayModes[mode].frequency;
+ if (diff < 0)
+ diff = -diff;
+
+ if (diff < minimum)
+ {
+ minimum = diff;
+ match = mode;
+ }
+ }
+ else
+ {
+ match = mode;
+ break;
+ }
+ }
+ }
+
+ /* RETURN DISPLAY MODE INDEX */
+
+ return match;
+}
+
+/*---------------------------------------------------------------------------
+ * vg_get_display_mode_information
+ *
+ * This routine retrieves all information for a display mode contained
+ * within Cimarron's mode tables.
+ *---------------------------------------------------------------------------*/
+
+int vg_get_display_mode_information (unsigned int index, VG_DISPLAY_MODE *vg_mode)
+{
+ if (index > NUM_CIMARRON_DISPLAY_MODES)
+ return CIM_STATUS_INVALIDPARAMS;
+
+ *vg_mode = CimarronDisplayModes[index];
+ return CIM_STATUS_OK;
+}
+
+/*---------------------------------------------------------------------------
+ * vg_get_display_mode_count
+ *
+ * This routine retrieves the count of all predefined Cimarron modes.
+ *---------------------------------------------------------------------------*/
+
+int vg_get_display_mode_count (void)
+{
+ return NUM_CIMARRON_DISPLAY_MODES;
+}
+
+/*---------------------------------------------------------------------------
+ * vg_get_current_display_mode
+ *
+ * This routine retrieves the settings for the current display. This includes
+ * any panel settings.
+ *---------------------------------------------------------------------------*/
+
+int vg_get_current_display_mode (VG_DISPLAY_MODE *current_display, int *bpp)
+{
+ Q_WORD msr_value;
+ unsigned long active, blank, sync;
+ unsigned long i, m, n, p;
+ unsigned long genlk, irq, temp;
+ unsigned long flags = 0;
+ unsigned long iflags = 0;
+
+ /* READ THE CURRENT HORIZONTAL DISPLAY TIMINGS */
+
+ active = READ_REG32 (DC3_H_ACTIVE_TIMING);
+ blank = READ_REG32 (DC3_H_BLANK_TIMING);
+ sync = READ_REG32 (DC3_H_SYNC_TIMING);
+
+ current_display->hactive = (active & 0xFFF) + 1;
+ current_display->hblankstart = (blank & 0xFFF) + 1;
+ current_display->hsyncstart = (sync & 0xFFF) + 1;
+
+ current_display->htotal = ((active >> 16) & 0xFFF) + 1;
+ current_display->hblankend = ((blank >> 16) & 0xFFF) + 1;
+ current_display->hsyncend = ((sync >> 16) & 0xFFF) + 1;
+
+ /* READ THE CURRENT VERTICAL DISPLAY TIMINGS */
+
+ active = READ_REG32 (DC3_V_ACTIVE_TIMING);
+ blank = READ_REG32 (DC3_V_BLANK_TIMING);
+ sync = READ_REG32 (DC3_V_SYNC_TIMING);
+
+ current_display->vactive = (active & 0x7FF) + 1;
+ current_display->vblankstart = (blank & 0x7FF) + 1;
+ current_display->vsyncstart = (sync & 0x7FF) + 1;
+
+ current_display->vtotal = ((active >> 16) & 0x7FF) + 1;
+ current_display->vblankend = ((blank >> 16) & 0x7FF) + 1;
+ current_display->vsyncend = ((sync >> 16) & 0x7FF) + 1;
+
+ /* READ THE CURRENT EVEN FIELD VERTICAL DISPLAY TIMINGS */
+
+ active = READ_REG32 (DC3_V_ACTIVE_EVEN);
+ blank = READ_REG32 (DC3_V_BLANK_EVEN);
+ sync = READ_REG32 (DC3_V_SYNC_EVEN);
+
+ current_display->vactive_even = (active & 0x7FF) + 1;
+ current_display->vblankstart_even = (blank & 0x7FF) + 1;
+ current_display->vsyncstart_even = (sync & 0x7FF) + 1;
+
+ current_display->vtotal_even = ((active >> 16) & 0x7FF) + 1;
+ current_display->vblankend_even = ((blank >> 16) & 0x7FF) + 1;
+ current_display->vsyncend_even = ((sync >> 16) & 0x7FF) + 1;
+
+ /* READ THE CURRENT SOURCE DIMENSIONS */
+ /* The DC3_FB_ACTIVE register is only used when scaling is enabled. */
+ /* As the goal of this routine is to return a structure that can be */
+ /* passed to vg_set_custom_mode to exactly recreate the current mode, */
+ /* we must check the status of the scaler/filter. */
+
+ genlk = READ_REG32 (DC3_GENLK_CTL);
+ irq = READ_REG32 (DC3_IRQ_FILT_CTL);
+ temp = READ_REG32 (DC3_FB_ACTIVE);
+
+ current_display->src_height = (temp & 0xFFFF) + 1;
+ current_display->src_width = ((temp >> 16) & 0xFFF8) + 8;
+
+ /* READ THE CURRENT PANEL CONFIGURATION */
+ /* We can only infer some of the panel settings based on hardware */
+ /* (like when panning). We will instead assume that the current */
+ /* mode was set using Cimarron and use the panel variables inside */
+ /* Cimarron when returning the current mode information. */
+
+ if (vg3_panel_enable)
+ {
+ Q_WORD msr_value;
+
+ flags |= VG_MODEFLAG_PANELOUT;
+
+ current_display->panel_width = vg3_panel_width;
+ current_display->panel_height = vg3_panel_height;
+ current_display->mode_width = vg3_mode_width;
+ current_display->mode_height = vg3_mode_height;
+
+ if (READ_REG32 (DC3_DISPLAY_CFG) & DC3_DCFG_DCEN)
+ flags |= VG_MODEFLAG_CENTERED;
+
+ msr_read64 (MSR_DEVICE_GEODELX_DF, DF_MSR_PAD_SEL, &msr_value);
+ current_display->panel_tim1 = READ_VID32 (DF_VIDEO_PANEL_TIM1);
+ current_display->panel_tim2 = READ_VID32 (DF_VIDEO_PANEL_TIM2);
+ current_display->panel_dither_ctl = READ_VID32 (DF_DITHER_CONTROL);
+ current_display->panel_pad_sel_low = msr_value.low;
+ current_display->panel_pad_sel_high = msr_value.high;
+ }
+
+ /* SET MISCELLANEOUS MODE FLAGS */
+
+ /* INTERLACED */
+
+ if (irq & DC3_IRQFILT_INTL_EN)
+ {
+ flags |= VG_MODEFLAG_INTERLACED;
+ if (irq & DC3_IRQFILT_INTL_ADDR)
+ flags |= VG_MODEFLAG_INT_ADDRESS;
+ else if (genlk & DC3_GC_FLICKER_FILTER_ENABLE)
+ flags |= VG_MODEFLAG_INT_FLICKER;
+ else
+ flags |= VG_MODEFLAG_INT_LINEDOUBLE;
+ }
+
+ /* POLARITIES */
+
+ temp = READ_VID32 (DF_DISPLAY_CONFIG);
+ if (temp & DF_DCFG_CRT_HSYNC_POL)
+ flags |= VG_MODEFLAG_NEG_HSYNC;
+ if (temp & DF_DCFG_CRT_VSYNC_POL)
+ flags |= VG_MODEFLAG_NEG_VSYNC;
+
+ /* BPP */
+
+ temp = READ_REG32 (DC3_DISPLAY_CFG) & DC3_DCFG_DISP_MODE_MASK;
+ if (temp == DC3_DCFG_DISP_MODE_8BPP)
+ {
+ iflags |= VG_SUPPORTFLAG_8BPP;
+ *bpp = 8;
+ }
+ else if (temp == DC3_DCFG_DISP_MODE_24BPP)
+ {
+ iflags |= VG_SUPPORTFLAG_24BPP;
+ *bpp = 24;
+ }
+ else if (temp == DC3_DCFG_DISP_MODE_32BPP)
+ {
+ iflags |= VG_SUPPORTFLAG_32BPP;
+ *bpp = 32;
+ }
+ else if (temp == DC3_DCFG_DISP_MODE_16BPP)
+ {
+ temp = READ_REG32 (DC3_DISPLAY_CFG) & DC3_DCFG_16BPP_MODE_MASK;
+ if (temp == DC3_DCFG_16BPP)
+ {
+ iflags |= VG_SUPPORTFLAG_16BPP;
+ *bpp = 16;
+ }
+ else if (temp == DC3_DCFG_15BPP)
+ {
+ iflags |= VG_SUPPORTFLAG_15BPP;
+ *bpp = 15;
+ }
+ else if (temp == DC3_DCFG_12BPP)
+ {
+ iflags |= VG_SUPPORTFLAG_12BPP;
+ *bpp = 12;
+ }
+ }
+
+ /* TV RELATED FLAGS */
+
+ msr_read64 (MSR_DEVICE_GEODELX_DF, DF_MSR_PAD_SEL, &msr_value);
+ if (msr_value.high & DF_INVERT_VOP_CLOCK)
+ flags |= VG_MODEFLAG_TVOUT;
+
+ /* LINEAR PITCH */
+
+ temp = (READ_REG32 (DC3_GFX_PITCH) & 0x0000FFFF) << 3;
+ if (temp != 1024 && temp != 2048 && temp != 4096 && temp != 8192)
+ flags |= VG_MODEFLAG_LINEARPITCH;
+
+ /* SIMULTANEOUS CRT/FP */
+
+ msr_read64 (MSR_DEVICE_GEODELX_DF, MSR_GEODELINK_CONFIG, &msr_value);
+ if (msr_value.low & DF_SIMULTANEOUS_CRT_FP)
+ flags |= VG_MODEFLAG_CRT_AND_FP;
+
+ /* SET PLL-RELATED FLAGS */
+
+ msr_read64 (MSR_DEVICE_GEODELX_GLCP, GLCP_DOTPLL, &msr_value);
+ if (msr_value.high & GLCP_DOTPLL_DIV4)
+ flags |= VG_MODEFLAG_QVGA;
+ if (msr_value.low & GLCP_DOTPLL_HALFPIX)
+ flags |= VG_MODEFLAG_HALFCLOCK;
+
+ /* SAVE THE FLAGS IN THE MODE STRUCTURE */
+
+ current_display->internal_flags = iflags;
+ current_display->flags = flags;
+
+ /* READ PIXEL CLOCK FREQUENCY */
+ /* We first search for an exact match. If none is found, we try */
+ /* a fixed point calculation and return CIM_STATUS_INEXACTMATCH. */
+
+ for (i = 0; i < NUM_CIMARRON_PLL_FREQUENCIES; i++)
+ {
+ if (CimarronPLLFrequencies[i].pll_value == msr_value.high)
+ break;
+ }
+
+ if (i == NUM_CIMARRON_PLL_FREQUENCIES)
+ {
+ /* ATTEMPT 16.16 CALCULATION */
+ /* We assume the input frequency is 48 MHz, which is represented */
+ /* in 16.16 fixed point as 0x300000. The PLL calculation is: */
+ /* n + 1 */
+ /* Fout = 48.000 * -------------- */
+ /* m + 1 * p + 1 */
+
+ p = msr_value.high & 0xF;
+ n = (msr_value.high >> 4) & 0xFF;
+ m = (msr_value.high >> 12) & 0x7;
+ current_display->frequency = (0x300000 * (n + 1)) / ((p + 1) * (m + 1));
+
+ return CIM_STATUS_INEXACTMATCH;
+ }
+
+ current_display->frequency = CimarronPLLFrequencies[i].frequency;
+
+ /* NOW SEARCH FOR AN IDENTICAL MODE */
+ /* This is just to inform the user that an exact match was found. */
+ /* With an exact match, the user can use the refresh rate flag that */
+ /* is returned in the VG_DISPLAY_MODE structure. */
+
+ for (i = 0; i < NUM_CIMARRON_DISPLAY_MODES; i++)
+ {
+ if ((CimarronDisplayModes[i].flags & current_display->flags) &&
+ CimarronDisplayModes[i].frequency == current_display->frequency &&
+ CimarronDisplayModes[i].hactive == current_display->hactive &&
+ CimarronDisplayModes[i].hblankstart == current_display->hblankstart &&
+ CimarronDisplayModes[i].hsyncstart == current_display->hsyncstart &&
+ CimarronDisplayModes[i].hsyncend == current_display->hsyncend &&
+ CimarronDisplayModes[i].hblankend == current_display->hblankend &&
+ CimarronDisplayModes[i].htotal == current_display->htotal &&
+ CimarronDisplayModes[i].vactive == current_display->vactive &&
+ CimarronDisplayModes[i].vblankstart == current_display->vblankstart &&
+ CimarronDisplayModes[i].vsyncstart == current_display->vsyncstart &&
+ CimarronDisplayModes[i].vsyncend == current_display->vsyncend &&
+ CimarronDisplayModes[i].vblankend == current_display->vblankend &&
+ CimarronDisplayModes[i].vtotal == current_display->vtotal)
+ {
+ break;
+ }
+ }
+
+ if (i == NUM_CIMARRON_DISPLAY_MODES)
+ return CIM_STATUS_INEXACTMATCH;
+
+ current_display->internal_flags |= (CimarronDisplayModes[i].internal_flags & VG_SUPPORTFLAG_HZMASK);
+ return CIM_STATUS_OK;
+}
+
+/*---------------------------------------------------------------------------
+ * vg_set_scaler_filter_coefficients
+ *
+ * This routine sets the vertical and horizontal filter coefficients for
+ * graphics scaling. If either of the input arrays is specified as NULL, a
+ * set of default coeffecients will be used.
+ *---------------------------------------------------------------------------*/
+
+int vg_set_scaler_filter_coefficients (long h_taps[][5], long v_taps[][3])
+{
+ unsigned long irqfilt, i;
+ unsigned long temp0, temp1;
+ unsigned long lock;
+
+ /* ENABLE ACCESS TO THE HORIZONTAL COEFFICIENTS */
+
+ irqfilt = READ_REG32 (DC3_IRQ_FILT_CTL);
+ irqfilt |= DC3_IRQFILT_H_FILT_SEL;
+
+ /* UNLOCK THE COEFFICIENT REGISTERS */
+
+ lock = READ_REG32 (DC3_UNLOCK);
+ WRITE_REG32 (DC3_UNLOCK, DC3_UNLOCK_VALUE);
+
+ /* WRITE COEFFICIENTS */
+ /* Coefficient indexes do not auto-increment, so we must */
+ /* write the address for every phase */
+
+ for (i = 0; i < 256; i++)
+ {
+ WRITE_REG32 (DC3_IRQ_FILT_CTL, ((irqfilt & 0xFFFFFF00L) | i));
+
+ if (!h_taps)
+ {
+ temp0 = CimarronHorizontalGraphicsFilter[i][0];
+ temp1 = CimarronHorizontalGraphicsFilter[i][1];
+ }
+ else
+ {
+ temp0 = ((unsigned long)h_taps[i][0] & 0x3FF) |
+ (((unsigned long)h_taps[i][1] & 0x3FF) << 10) |
+ (((unsigned long)h_taps[i][2] & 0x3FF) << 20);
+
+ temp1 = ((unsigned long)h_taps[i][3] & 0x3FF) |
+ (((unsigned long)h_taps[i][4] & 0x3FF) << 10);
+ }
+ WRITE_REG32 (DC3_FILT_COEFF1, temp0);
+ WRITE_REG32 (DC3_FILT_COEFF2, temp1);
+ }
+
+ /* ENABLE ACCESS TO THE VERTICAL COEFFICIENTS */
+
+ irqfilt &= ~DC3_IRQFILT_H_FILT_SEL;
+
+ /* WRITE COEFFICIENTS */
+
+ for (i = 0; i < 256; i++)
+ {
+ WRITE_REG32 (DC3_IRQ_FILT_CTL, ((irqfilt & 0xFFFFFF00L) | i));
+
+ if (!v_taps)
+ {
+ temp0 = CimarronVerticalGraphicsFilter[i];
+ }
+ else
+ {
+ temp0 = ((unsigned long)v_taps[i][0] & 0x3FF) |
+ (((unsigned long)v_taps[i][1] & 0x3FF) << 10) |
+ (((unsigned long)v_taps[i][2] & 0x3FF) << 20);
+ }
+
+ WRITE_REG32 (DC3_FILT_COEFF1, temp0);
+ }
+
+ WRITE_REG32 (DC3_UNLOCK, lock);
+
+ return CIM_STATUS_OK;
+}
+
+/*---------------------------------------------------------------------------
+ * vg_configure_flicker_filter
+ *
+ * This routine updates the VG flicker filter settings when in an interlaced
+ * mode. Note that flicker filtering is enabled inside a mode set. This routine
+ * is provided to change from the default flicker filter setting of
+ * 1/4, 1/2, 1/4.
+ *---------------------------------------------------------------------------*/
+
+int vg_configure_flicker_filter (unsigned long flicker_strength, int flicker_alpha)
+{
+ unsigned long unlock;
+ unsigned long genlk_ctl;
+
+ /* CHECK FOR VALID FLICKER SETTING */
+
+ if (flicker_strength != VG_FLICKER_FILTER_NONE &&
+ flicker_strength != VG_FLICKER_FILTER_1_16 &&
+ flicker_strength != VG_FLICKER_FILTER_1_8 &&
+ flicker_strength != VG_FLICKER_FILTER_1_4 &&
+ flicker_strength != VG_FLICKER_FILTER_5_16)
+ {
+ return CIM_STATUS_INVALIDPARAMS;
+ }
+
+ unlock = READ_REG32 (DC3_UNLOCK);
+ genlk_ctl = READ_REG32 (DC3_GENLK_CTL) & ~(DC3_GC_FLICKER_FILTER_MASK | DC3_GC_ALPHA_FLICK_ENABLE);
+ genlk_ctl |= flicker_strength;
+ if (flicker_alpha)
+ genlk_ctl |= DC3_GC_ALPHA_FLICK_ENABLE;
+
+ WRITE_REG32 (DC3_UNLOCK, DC3_UNLOCK_VALUE);
+ WRITE_REG32 (DC3_GENLK_CTL, genlk_ctl);
+ WRITE_REG32 (DC3_UNLOCK, unlock);
+
+ return CIM_STATUS_OK;
+}
+
+/*---------------------------------------------------------------------------
+ * vg_set_clock_frequency
+ *
+ * This routine sets the frequency of the dot clock. The input to this routine
+ * is a 16.16 fraction. If an exact match is not found, this routine will program
+ * the closest available frequency and return CIM_STATUS_INEXACTMATCH.
+ *---------------------------------------------------------------------------*/
+
+int vg_set_clock_frequency (unsigned long frequency, unsigned long pll_flags)
+{
+ Q_WORD msr_value;
+ unsigned long timeout;
+ unsigned long index = 0;
+ unsigned long unlock, i;
+ unsigned long pll_high, pll_low;
+ long diff, min = 0;
+
+ /* FIND THE REGISTER VALUES FOR THE DESIRED FREQUENCY */
+ /* Search the table for the closest frequency (16.16 format). */
+ /* This search is skipped if the user is manually specifying */
+ /* the MSR value. */
+
+ pll_low = 0;
+ if (!(pll_flags & VG_PLL_MANUAL))
+ {
+ min = (long)CimarronPLLFrequencies[0].frequency - (long)frequency;
+ if (min < 0L)
+ min = -min;
+
+ for (i = 1; i < NUM_CIMARRON_PLL_FREQUENCIES; i++)
+ {
+ diff = (long)CimarronPLLFrequencies[i].frequency - (long)frequency;
+ if (diff < 0L)
+ diff = -diff;
+
+ if (diff < min)
+ {
+ min = diff;
+ index = i;
+ }
+ }
+
+ pll_high = CimarronPLLFrequencies[index].pll_value & 0x00007FFF;
+ }
+ else
+ {
+ pll_high = frequency;
+ }
+
+ if (pll_flags & VG_PLL_DIVIDE_BY_2)
+ pll_low |= GLCP_DOTPLL_HALFPIX;
+ if (pll_flags & VG_PLL_DIVIDE_BY_4)
+ pll_high |= GLCP_DOTPLL_DIV4;
+ if (pll_flags & VG_PLL_BYPASS)
+ pll_low |= GLCP_DOTPLL_BYPASS;
+ if (pll_flags & VG_PLL_VIP_CLOCK)
+ pll_high |= GLCP_DOTPLL_VIPCLK;
+
+ /* VERIFY THAT WE ARE NOT WRITING WHAT IS ALREADY IN THE REGISTERS */
+ /* The Dot PLL reset bit is tied to VDD for flat panels. This can */
+ /* cause a brief drop in flat panel power, which can cause serious */
+ /* glitches on some panels. */
+
+ msr_read64 (MSR_DEVICE_GEODELX_GLCP, GLCP_DOTPLL, &msr_value);
+
+ if ((msr_value.low & GLCP_DOTPLL_LOCK) &&
+ ((msr_value.low & (GLCP_DOTPLL_HALFPIX | GLCP_DOTPLL_BYPASS)) == pll_low) &&
+ (msr_value.high == pll_high))
+ {
+ return CIM_STATUS_OK;
+ }
+
+ /* PROGRAM THE SETTINGS WITH THE RESET BIT SET */
+ /* Clear the bypass bit to ensure that the programmed */
+ /* M, N and P values are being used. */
+
+ msr_value.high = pll_high;
+ msr_value.low &= ~(GLCP_DOTPLL_BYPASS | GLCP_DOTPLL_HALFPIX);
+ msr_value.low |= (pll_low | 0x00000001);
+ msr_write64 (MSR_DEVICE_GEODELX_GLCP, GLCP_DOTPLL, &msr_value);
+
+ /* WAIT FOR THE LOCK BIT */
+ /* The PLL spec states that the PLL may take up to 100 us to */
+ /* properly lock. Furthermore, the lock signal is not 100% */
+ /* reliable. To address this, we add a hefty delay followed */
+ /* by a polling loop that times out after a 1000 reads. */
+
+ unlock = READ_REG32 (DC3_UNLOCK);
+ for (timeout = 0; timeout < 1280; timeout++)
+ WRITE_REG32 (DC3_UNLOCK, unlock);
+
+ for (timeout = 0; timeout < 1000; timeout++)
+ {
+ msr_read64 (MSR_DEVICE_GEODELX_GLCP, GLCP_DOTPLL, &msr_value);
+ if (msr_value.low & GLCP_DOTPLL_LOCK)
+ break;
+ }
+
+ /* CLEAR THE RESET BIT */
+
+ msr_value.low &= 0xFFFFFFFE;
+ msr_write64 (MSR_DEVICE_GEODELX_GLCP, GLCP_DOTPLL, &msr_value);
+
+ /* DID THE PLL SUCCESSFULLY LOCK? */
+
+ if (!(msr_value.low & GLCP_DOTPLL_LOCK))
+ return CIM_STATUS_NOLOCK;
+
+ /* RETURN THE APPROPRIATE CODE */
+
+ if (min == 0)
+ return CIM_STATUS_OK;
+ else
+ return CIM_STATUS_INEXACTMATCH;
+}
+
+/*---------------------------------------------------------------------------
+ * vg_set_border_color
+ *
+ * This routine sets the color used as the border in centered panel modes.
+ *---------------------------------------------------------------------------*/
+
+int vg_set_border_color (unsigned long border_color)
+{
+ unsigned long lock = READ_REG32 (DC3_UNLOCK);
+
+ WRITE_REG32 (DC3_UNLOCK, DC3_UNLOCK_VALUE);
+ WRITE_REG32 (DC3_PAL_ADDRESS, 0x104);
+ WRITE_REG32 (DC3_PAL_DATA, border_color);
+ WRITE_REG32 (DC3_UNLOCK, lock);
+
+ return CIM_STATUS_OK;
+}
+
+/*---------------------------------------------------------------------------
+ * vg_set_cursor_enable
+ *
+ * This routine enables or disables the hardware cursor. This routine should
+ * only be called after the hardware cursor has been completely configured.
+ *---------------------------------------------------------------------------*/
+
+int vg_set_cursor_enable(int enable)
+{
+ unsigned long unlock, gcfg;
+
+ /* SET OR CLEAR CURSOR ENABLE BIT */
+
+ unlock = READ_REG32(DC3_UNLOCK);
+ gcfg = READ_REG32(DC3_GENERAL_CFG);
+ if (enable) gcfg |= DC3_GCFG_CURE;
+ else gcfg &= ~(DC3_GCFG_CURE);
+
+ /* WRITE NEW REGISTER VALUE */
+
+ WRITE_REG32 (DC3_UNLOCK, DC3_UNLOCK_VALUE);
+ WRITE_REG32 (DC3_GENERAL_CFG, gcfg);
+ WRITE_REG32 (DC3_UNLOCK, unlock);
+
+ return CIM_STATUS_OK;
+}
+
+/*---------------------------------------------------------------------------
+ * vg_set_mono_cursor_colors
+ *
+ * This routine sets the colors of the hardware monochrome cursor.
+ *---------------------------------------------------------------------------*/
+
+int vg_set_mono_cursor_colors (unsigned long bkcolor, unsigned long fgcolor)
+{
+ unsigned long lock = READ_REG32 (DC3_UNLOCK);
+
+ /* SET CURSOR COLORS */
+
+ WRITE_REG32 (DC3_UNLOCK, DC3_UNLOCK_VALUE);
+ WRITE_REG32 (DC3_PAL_ADDRESS, 0x100);
+ WRITE_REG32 (DC3_PAL_DATA, bkcolor);
+ WRITE_REG32 (DC3_PAL_DATA, fgcolor);
+ WRITE_REG32 (DC3_UNLOCK, lock);
+
+ return CIM_STATUS_OK;
+}
+
+/*---------------------------------------------------------------------------
+ * vg_set_cursor_position
+ *
+ * This routine sets the position of the hardware cursor. The cursor hotspots
+ * and memory offset must have been specified in an earlier call to
+ * a vg_set_cursor_shape_XX routine. The coordinates passed to this routine
+ * generally specify the focal point of the cursor, NOT the upper left coordinate of
+ * the cursor pattern. However, for operating systems that do not include a hotspot
+ * the input parameters may be negative.
+ *---------------------------------------------------------------------------*/
+
+int vg_set_cursor_position (long xpos, long ypos, VG_PANNING_COORDINATES *panning)
+{
+ unsigned long unlock, memoffset;
+ unsigned long gcfg;
+ long x, xoffset;
+ long y, yoffset;
+
+ memoffset = vg3_cursor_offset;
+ x = xpos - (long) vg3_x_hotspot;
+ y = ypos - (long) vg3_y_hotspot;
+
+ /* HANDLE NEGATIVE COORDINATES */
+ /* This routine supports operating systems that use negative */
+ /* coordinates, instead of positive coordinates with an appropriate */
+ /* hotspot. */
+
+ if (xpos < 0) xpos = 0;
+ if (ypos < 0) ypos = 0;
+
+ if (x < -63) return CIM_STATUS_INVALIDPARAMS;
+ if (y < -63) return CIM_STATUS_INVALIDPARAMS;
+
+ if (vg3_panel_enable)
+ {
+ if ((vg3_mode_width > vg3_panel_width) || (vg3_mode_height > vg3_panel_height))
+ {
+ vg_pan_desktop (xpos, ypos, panning);
+ x = x - (unsigned short)vg3_delta_x;
+ y = y - (unsigned short)vg3_delta_y;
+ }
+ else
+ {
+ panning->start_x = 0;
+ panning->start_y = 0;
+ panning->start_updated = 0;
+ }
+ }
+
+ /* ADJUST OFFSETS */
+ /* Cursor movement and panning work as follows: The cursor position */
+ /* refers to where the hotspot of the cursor is located. However, for */
+ /* non-zero hotspots, the cursor buffer actually begins before the */
+ /* specified position. */
+
+ if (x < 0) { xoffset = -x; x = 0; }
+ else { xoffset = 0; }
+ if (y < 0) { yoffset = -y; y = 0; }
+ else { yoffset = 0; }
+
+ if (vg3_color_cursor) memoffset += (unsigned long) yoffset * 192;
+ else memoffset += (unsigned long) yoffset << 4;
+
+ /* SET COLOR CURSOR BIT */
+
+ gcfg = READ_REG32(DC3_GENERAL_CFG);
+ if (vg3_color_cursor)
+ gcfg |= DC3_GCFG_CLR_CUR;
+ else
+ gcfg &= ~DC3_GCFG_CLR_CUR;
+
+ /* SET CURSOR POSITION */
+
+ unlock = READ_REG32(DC3_UNLOCK);
+ WRITE_REG32(DC3_UNLOCK, DC3_UNLOCK_VALUE);
+ WRITE_REG32 (DC3_CURS_ST_OFFSET, memoffset);
+ WRITE_REG32 (DC3_GENERAL_CFG, gcfg);
+ WRITE_REG32 (DC3_CURSOR_X, (unsigned long) x |
+ (((unsigned long) xoffset) << 11));
+ WRITE_REG32 (DC3_CURSOR_Y, (unsigned long) y |
+ (((unsigned long) yoffset) << 11));
+ WRITE_REG32 (DC3_UNLOCK, unlock);
+
+ return CIM_STATUS_OK;
+}
+
+/*---------------------------------------------------------------------------
+ * vg_set_mono_cursor_shape32
+ *
+ * This routine loads 32x32 cursor data into the cursor buffer in graphics memory.
+ * The outside of the GeodeLX cursor buffer is padded with transparency.
+ *---------------------------------------------------------------------------*/
+
+int vg_set_mono_cursor_shape32 (unsigned long memoffset, unsigned long *andmask,
+ unsigned long *xormask, unsigned long x_hotspot, unsigned long y_hotspot)
+{
+ int i;
+
+ /* SAVE THE CURSOR OFFSET AND HOTSPOTS */
+ /* These are reused later when updating the cursor position, panning */
+ /* and clipping the cursor pointer. */
+
+ vg3_x_hotspot = x_hotspot;
+ vg3_y_hotspot = y_hotspot;
+ vg3_cursor_offset = memoffset;
+ vg3_color_cursor = 0;
+
+ for (i = 0; i < 32; i++)
+ {
+ /* EVEN QWORDS CONTAIN THE AND MASK */
+
+ WRITE_FB32 (memoffset, 0xFFFFFFFF);
+ WRITE_FB32 (memoffset + 4, andmask[i]);
+
+ /* ODD QWORDS CONTAIN THE XOR MASK */
+
+ WRITE_FB32 (memoffset + 8, 0x00000000);
+ WRITE_FB32 (memoffset + 12, xormask[i]);
+
+ memoffset += 16;
+ }
+
+ /* FILL THE LOWER HALF OF THE BUFFER WITH TRANSPARENT PIXELS */
+
+ for (i = 0; i < 32; i++)
+ {
+ WRITE_FB32 (memoffset, 0xFFFFFFFF);
+ WRITE_FB32 (memoffset + 4, 0xFFFFFFFF);
+ WRITE_FB32 (memoffset + 8, 0x00000000);
+ WRITE_FB32 (memoffset + 12, 0x00000000);
+
+ memoffset += 16;
+ }
+
+ return CIM_STATUS_OK;
+}
+
+/*---------------------------------------------------------------------------
+ * vg_set_mono_cursor_shape64
+ *
+ * This routine loads 64x64 cursor data into the cursor buffer in graphics memory.
+ *---------------------------------------------------------------------------*/
+
+int vg_set_mono_cursor_shape64 (unsigned long memoffset, unsigned long *andmask,
+ unsigned long *xormask, unsigned long x_hotspot, unsigned long y_hotspot)
+{
+ int i;
+
+ /* SAVE THE CURSOR OFFSET AND HOTSPOTS */
+ /* These are reused later when updating the cursor position, panning */
+ /* and clipping the cursor pointer. */
+
+ vg3_x_hotspot = x_hotspot;
+ vg3_y_hotspot = y_hotspot;
+ vg3_cursor_offset = memoffset;
+ vg3_color_cursor = 0;
+
+ for (i = 0; i < 128; i += 2)
+ {
+ /* EVEN QWORDS CONTAIN THE AND MASK */
+ /* We invert the dwords to prevent the calling */
+ /* application from having to think in terms of Qwords. */
+ /* The hardware data order is actually 63:0, or 31:0 of */
+ /* the second dword followed by 31:0 of the first dword. */
+
+ WRITE_FB32 (memoffset, andmask[i + 1]);
+ WRITE_FB32 (memoffset + 4, andmask[i]);
+
+ /* ODD QWORDS CONTAIN THE XOR MASK */
+
+ WRITE_FB32 (memoffset + 8, xormask[i + 1]);
+ WRITE_FB32 (memoffset + 12, xormask[i]);
+
+ memoffset += 16;
+ }
+
+ return CIM_STATUS_OK;
+}
+
+/*---------------------------------------------------------------------------
+ * vg_set_color_cursor_shape
+ *
+ * This routine loads 8:8:8:8 cursor data into the color cursor buffer.
+ *---------------------------------------------------------------------------*/
+
+int vg_set_color_cursor_shape (unsigned long memoffset, unsigned char *data,
+ unsigned long width, unsigned long height, long pitch,
+ unsigned long x_hotspot, unsigned long y_hotspot)
+{
+ unsigned long y;
+
+ /* SAVE THE CURSOR OFFSET AND HOTSPOTS */
+ /* These are reused later when updating the cursor position, panning */
+ /* and clipping the cursor pointer. */
+
+ vg3_x_hotspot = x_hotspot;
+ vg3_y_hotspot = y_hotspot;
+ vg3_cursor_offset = memoffset;
+ vg3_color_cursor = 1;
+
+ /* WRITE THE CURSOR DATA */
+ /* The outside edges of the color cursor are filled with transparency */
+ /* The cursor buffer dimensions are 48x64. */
+
+ for (y = 0; y < height; y++)
+ {
+ /* WRITE THE ACTIVE AND TRANSPARENT DATA */
+ /* We implement this as a macro in our dedication to squeaking */
+ /* every ounce of performance out of our code... */
+
+ WRITE_FB_STRING32 (memoffset, data, width);
+ WRITE_FB_CONSTANT ((memoffset + (width << 2)), 0, (48 - width));
+
+ /* INCREMENT PAST THE LINE */
+
+ memoffset += 192;
+ data += pitch;
+ }
+
+ /* WRITE THE EXTRA TRANSPARENT LINES */
+ /* Write the lines in one big bulk setting. */
+
+ WRITE_FB_CONSTANT (memoffset, 0, ((64 - height) * 48));
+
+ return CIM_STATUS_OK;
+}
+
+/*---------------------------------------------------------------------------
+ * vg_pan_desktop
+ *
+ * This routine sets the correct display offset based on the current cursor
+ * position.
+ *---------------------------------------------------------------------------*/
+
+int vg_pan_desktop (unsigned long x, unsigned long y, VG_PANNING_COORDINATES *panning)
+{
+ unsigned long modeShiftPerPixel;
+ unsigned long modeBytesPerScanline;
+ unsigned long startAddress;
+
+ /* TEST FOR NO-WORK */
+
+ if (x >= vg3_delta_x && x < (vg3_panel_width + vg3_delta_x) &&
+ y >= vg3_delta_y && y < (vg3_panel_height + vg3_delta_y))
+ {
+ panning->start_x = vg3_delta_x;
+ panning->start_y = vg3_delta_y;
+ panning->start_updated = 0;
+ return CIM_STATUS_OK;
+ }
+
+ if (vg3_bpp == 24) modeShiftPerPixel = 2;
+ else modeShiftPerPixel = (vg3_bpp + 7) >> 4;
+
+ modeBytesPerScanline = (READ_REG32 (DC3_GFX_PITCH) & 0x0000FFFF) << 3;
+
+ /* ADJUST PANNING VARIABLES WHEN CURSOR EXCEEDS BOUNDARY */
+ /* Test the boundary conditions for each coordinate and update */
+ /* all variables and the starting offset accordingly. */
+
+ if (x < vg3_delta_x)
+ vg3_delta_x = x;
+
+ else if (x >= (vg3_delta_x + vg3_panel_width))
+ vg3_delta_x = x - vg3_panel_width + 1;
+
+ if (y < vg3_delta_y)
+ vg3_delta_y = y;
+
+ else if (y >= (vg3_delta_y + vg3_panel_height))
+ vg3_delta_y = y - vg3_panel_height + 1;
+
+ /* CALCULATE THE START OFFSET */
+
+ startAddress = (vg3_delta_x << modeShiftPerPixel) + (vg3_delta_y * modeBytesPerScanline);
+
+ vg_set_display_offset (startAddress);
+
+ panning->start_updated = 1;
+ panning->start_x = vg3_delta_x;
+ panning->start_y = vg3_delta_y;
+ return CIM_STATUS_OK;
+}
+
+/*---------------------------------------------------------------------------
+ * vg_set_display_offset
+ *
+ * This routine sets the start address of the frame buffer. It is
+ * typically used to pan across a virtual desktop (frame buffer larger than
+ * the displayed screen) or to flip the display between multiple buffers.
+ *---------------------------------------------------------------------------*/
+
+int vg_set_display_offset (unsigned long address)
+{
+ unsigned long lock, gcfg;
+
+ lock = READ_REG32 (DC3_UNLOCK);
+ WRITE_REG32 (DC3_UNLOCK, DC3_UNLOCK_VALUE);
+
+ /* DISABLE COMPRESSION */
+ /* When setting a non-zero display offset, we must disable display */
+ /* compression. We could maintain a variable and re-enable */
+ /* compression when the offset returns to zero. However, that */
+ /* creates additional complexity for applications that perform */
+ /* graphics animation. Re-enabling compression each time would */
+ /* be tedious and slow for such applications, implying that they */
+ /* would have to disable compression before starting the animation. */
+ /* We will instead disable compression and force the user to */
+ /* re-enable compression when they are ready. */
+
+ if (address != 0)
+ {
+ if (READ_REG32 (DC3_GENERAL_CFG) & DC3_GCFG_CMPE)
+ {
+ gcfg = READ_REG32 (DC3_GENERAL_CFG);
+ WRITE_REG32 (DC3_GENERAL_CFG, (gcfg & ~(DC3_GCFG_CMPE | DC3_GCFG_DECE)));
+ }
+ }
+
+ WRITE_REG32 (DC3_FB_ST_OFFSET, address);
+ WRITE_REG32 (DC3_UNLOCK, lock);
+
+ return CIM_STATUS_OK;
+}
+
+/*---------------------------------------------------------------------------
+ * vg_set_display_pitch
+ *
+ * This routine sets the stride between successive lines of data in the frame
+ * buffer.
+ *---------------------------------------------------------------------------*/
+
+int vg_set_display_pitch (unsigned long pitch)
+{
+ unsigned long dvtop, value;
+ unsigned long lock = READ_REG32(DC3_UNLOCK);
+
+ value = READ_REG32(DC3_GFX_PITCH) & 0xFFFF0000;
+ value |= (pitch >> 3);
+
+ /* PROGRAM THE DISPLAY PITCH */
+
+ WRITE_REG32 (DC3_UNLOCK, DC3_UNLOCK_VALUE);
+ WRITE_REG32 (DC3_GFX_PITCH, value);
+
+ /* SET THE COMPRESSION BEHAVIOR BASED ON THE PITCH */
+ /* Strides that are not a power of two will not work with line */
+ /* by line compression. For these cases, we enable full-screen */
+ /* compression. In this mode, any write to the frame buffer */
+ /* region marks the entire frame as dirty. */
+
+ value = READ_REG32 (DC3_GENERAL_CFG);
+
+ if (pitch == 1024 || pitch == 2048 || pitch == 4096 || pitch == 8192)
+ {
+ value &= ~DC3_GCFG_FDTY;
+ dvtop = 0;
+ }
+ else
+ {
+ value |= DC3_GCFG_FDTY;
+
+ dvtop = (READ_REG32 (DC3_FB_ACTIVE) & 0xFFF) + 1;
+ dvtop = ((dvtop * pitch) + 0x3FF) & 0xFFFFFC00;
+ dvtop |= DC3_DVTOP_ENABLE;
+ }
+
+ WRITE_REG32 (DC3_GENERAL_CFG, value);
+ WRITE_REG32 (DC3_DV_TOP, dvtop);
+ WRITE_REG32 (DC3_UNLOCK, lock);
+
+ return CIM_STATUS_OK;
+}
+
+/*---------------------------------------------------------------------------
+ * vg_set_display_palette_entry
+ *
+ * This routine sets a single 8BPP palette entry in the display controller.
+ *---------------------------------------------------------------------------*/
+
+int vg_set_display_palette_entry (unsigned long index, unsigned long palette)
+{
+ unsigned long dcfg, unlock;
+
+ if (index > 0xFF)
+ return CIM_STATUS_INVALIDPARAMS;
+
+ unlock = READ_REG32 (DC3_UNLOCK);
+ dcfg = READ_REG32 (DC3_DISPLAY_CFG);
+
+ WRITE_REG32 (DC3_UNLOCK, DC3_UNLOCK_VALUE);
+ WRITE_REG32 (DC3_DISPLAY_CFG, dcfg & ~DC3_DCFG_PALB);
+ WRITE_REG32 (DC3_UNLOCK, unlock);
+
+ WRITE_REG32 (DC3_PAL_ADDRESS, index);
+ WRITE_REG32 (DC3_PAL_DATA, palette);
+
+ return CIM_STATUS_OK;
+}
+
+/*---------------------------------------------------------------------------
+ * vg_set_display_palette
+ *
+ * This routine sets the entire palette in the display controller.
+ * A pointer is provided to a 256 entry table of 32-bit X:R:G:B values.
+ *---------------------------------------------------------------------------*/
+
+int vg_set_display_palette (unsigned long *palette)
+{
+ unsigned long unlock, dcfg, i;
+ WRITE_REG32 (DC3_PAL_ADDRESS, 0);
+
+ if (palette)
+ {
+ unlock = READ_REG32 (DC3_UNLOCK);
+ dcfg = READ_REG32 (DC3_DISPLAY_CFG);
+
+ WRITE_REG32 (DC3_UNLOCK, DC3_UNLOCK_VALUE);
+ WRITE_REG32 (DC3_DISPLAY_CFG, dcfg & ~DC3_DCFG_PALB);
+ WRITE_REG32 (DC3_UNLOCK, unlock);
+
+ for (i = 0; i < 256; i++)
+ WRITE_REG32 (DC3_PAL_DATA, palette[i]);
+
+ return CIM_STATUS_OK;
+ }
+ return CIM_STATUS_INVALIDPARAMS;
+}
+
+/*---------------------------------------------------------------------------
+ * vg_set_compression_enable
+ *
+ * This routine enables or disables display compression.
+ *---------------------------------------------------------------------------*/
+
+int vg_set_compression_enable (int enable)
+{
+ Q_WORD msr_value;
+ unsigned long unlock, gcfg;
+ unsigned long temp;
+
+ unlock = READ_REG32 (DC3_UNLOCK);
+ gcfg = READ_REG32 (DC3_GENERAL_CFG);
+ WRITE_REG32 (DC3_UNLOCK, DC3_UNLOCK_VALUE);
+
+ if (enable)
+ {
+ /* DO NOT ENABLE IF THE DISPLAY OFFSET IS NOT ZERO */
+
+ if (READ_REG32 (DC3_FB_ST_OFFSET) & 0x0FFFFFFF)
+ return CIM_STATUS_ERROR;
+
+ /* ENABLE BIT 1 IN THE VG SPARE MSR */
+ /* The bus can hang when the VG attempts to merge compression writes. */
+ /* No performance is lost due to the GeodeLink QUACK features in */
+ /* GeodeLX. We also enable the command word check for a valid */
+ /* compression header. */
+
+ msr_read64 (MSR_DEVICE_GEODELX_VG, DC3_SPARE_MSR, &msr_value);
+ msr_value.low |= DC3_SPARE_FIRST_REQ_MASK;
+ msr_value.low &= ~DC3_SPARE_DISABLE_CWD_CHECK;
+ msr_write64 (MSR_DEVICE_GEODELX_VG, DC3_SPARE_MSR, &msr_value);
+
+ /* CLEAR DIRTY/VALID BITS IN MEMORY CONTROLLER */
+ /* We don't want the controller to think that old lines are still */
+ /* valid. Writing a 1 to bit 0 of the DV Control register will force */
+ /* the hardware to clear all the valid bits. */
+
+ temp = READ_REG32 (DC3_DV_CTL);
+ WRITE_REG32 (DC3_DV_CTL, temp | 0x00000001);
+
+ /* ENABLE COMPRESSION BITS */
+
+ gcfg |= DC3_GCFG_CMPE | DC3_GCFG_DECE;
+ }
+ else
+ {
+ gcfg &= ~(DC3_GCFG_CMPE | DC3_GCFG_DECE);
+ }
+
+ WRITE_REG32 (DC3_GENERAL_CFG, gcfg);
+ WRITE_REG32 (DC3_UNLOCK, unlock);
+
+ return CIM_STATUS_OK;
+}
+
+/*---------------------------------------------------------------------------
+ * vg_configure_compression
+ *
+ * This routine configures all aspects of display compression, including pitch,
+ * size and the offset of the compression buffer.
+ *---------------------------------------------------------------------------*/
+
+int vg_configure_compression (VG_COMPRESSION_DATA *comp_data)
+{
+ unsigned long delta, size;
+ unsigned long comp_size, unlock;
+
+ /* CHECK FOR VALID PARAMETERS */
+ /* The maximum size for the compression buffer is 544 bytes (with */
+ /* the header) Also, the pitch cannot be less than the line size */
+ /* and the compression buffer offset must be 16-byte aligned. */
+
+ if (comp_data->size > 544 || comp_data->pitch < comp_data->size ||
+ comp_data->compression_offset & 0x0F)
+ {
+ return CIM_STATUS_INVALIDPARAMS;
+ }
+
+ /* SUBTRACT 32 FROM SIZE */
+ /* The display controller will actually write 4 extra QWords. So, */
+ /* if we assume that "size" refers to the allocated size, we must */
+ /* subtract 32 bytes. */
+
+ comp_size = comp_data->size - 32;
+
+ /* CALCULATE REGISTER VALUES */
+
+ unlock = READ_REG32 (DC3_UNLOCK);
+ size = READ_REG32 (DC3_LINE_SIZE) & ~DC3_LINE_SIZE_CBLS_MASK;
+ delta = READ_REG32 (DC3_GFX_PITCH) & ~DC3_GFX_PITCH_CBP_MASK;
+
+ size |= ((comp_size >> 3) + 1) << DC3_LINE_SIZE_CB_SHIFT;
+ delta |= ((comp_data->pitch >> 3) << 16);
+
+ /* WRITE COMPRESSION PARAMETERS */
+
+ WRITE_REG32 (DC3_UNLOCK, DC3_UNLOCK_VALUE);
+ WRITE_REG32 (DC3_CB_ST_OFFSET, comp_data->compression_offset);
+ WRITE_REG32 (DC3_LINE_SIZE, size);
+ WRITE_REG32 (DC3_GFX_PITCH, delta);
+ WRITE_REG32 (DC3_UNLOCK, unlock);
+
+ return CIM_STATUS_OK;
+}
+
+/*---------------------------------------------------------------------------
+ * vg_test_timing_active
+ *
+ * This routine checks the status of the display timing generator.
+ *---------------------------------------------------------------------------*/
+
+int vg_test_timing_active (void)
+{
+ if (READ_REG32 (DC3_DISPLAY_CFG) & DC3_DCFG_TGEN)
+ return 1;
+
+ return 0;
+}
+
+/*---------------------------------------------------------------------------
+ * vg_test_vertical_active
+ *
+ * This routine checks if the display is currently in the middle of a frame
+ * (not in the VBlank interval)
+ *---------------------------------------------------------------------------*/
+
+int vg_test_vertical_active (void)
+{
+ if (READ_REG32 (DC3_LINE_CNT_STATUS) & DC3_LNCNT_VNA)
+ return 0;
+
+ return 1;
+}
+
+/*---------------------------------------------------------------------------
+ * vg_wait_vertical_blank
+ *
+ * This routine waits until the beginning of the vertical blank interval.
+ * When the display is already in vertical blank, this routine will wait until
+ * the beginning of the next vertical blank.
+ *---------------------------------------------------------------------------*/
+
+int vg_wait_vertical_blank(void)
+{
+ if (vg_test_timing_active())
+ {
+ while (!vg_test_vertical_active());
+ while (vg_test_vertical_active());
+ }
+ return CIM_STATUS_OK;
+}
+
+/*---------------------------------------------------------------------------
+ * vg_test_even_field
+ *
+ * This routine tests the odd/even status of the current VG output field.
+ *---------------------------------------------------------------------------*/
+
+int vg_test_even_field(void)
+{
+ if (READ_REG32 (DC3_LINE_CNT_STATUS) & DC3_LNCNT_EVEN_FIELD)
+ return 1;
+
+ return 0;
+}
+
+/*---------------------------------------------------------------------------
+ * vg_configure_line_interrupt
+ *
+ * This routine configures the display controller's line count interrupt. This
+ * interrupt can be used to interrupt mid-frame or to interrupt at the beginning
+ * of vertical blank.
+ *---------------------------------------------------------------------------*/
+
+int vg_configure_line_interrupt (VG_INTERRUPT_PARAMS *interrupt_info)
+{
+ unsigned long irq_line, irq_enable;
+ unsigned long lock;
+
+ irq_line = READ_REG32 (DC3_IRQ_FILT_CTL);
+ irq_enable = READ_REG32 (DC3_IRQ);
+ lock = READ_REG32 (DC3_UNLOCK);
+
+ irq_line = (irq_line & ~DC3_IRQFILT_LINE_MASK) | ((interrupt_info->line << 16) & DC3_IRQFILT_LINE_MASK);
+
+ /* ENABLE OR DISABLE THE INTERRUPT */
+ /* The line count is set before enabling and after disabling to */
+ /* minimize spurious interrupts. The line count is set even */
+ /* when interrupts are disabled to allow polling-based or debug */
+ /* applications. */
+
+ WRITE_REG32 (DC3_UNLOCK, DC3_UNLOCK_VALUE);
+ if (interrupt_info->enable)
+ {
+ WRITE_REG32 (DC3_IRQ_FILT_CTL, irq_line);
+ WRITE_REG32 (DC3_IRQ, ((irq_enable & ~DC3_IRQ_MASK) | DC3_IRQ_STATUS));
+ }
+ else
+ {
+ WRITE_REG32 (DC3_IRQ, (irq_enable | DC3_IRQ_MASK));
+ WRITE_REG32 (DC3_IRQ_FILT_CTL, irq_line);
+ }
+ WRITE_REG32 (DC3_UNLOCK, lock);
+ return CIM_STATUS_OK;
+}
+
+/*---------------------------------------------------------------------------
+ * vg_test_and_clear_interrupt
+ *
+ * This routine resets any pending interrupt in the video generator. The return
+ * value indicates the interrupt status prior to the reset.
+ *---------------------------------------------------------------------------*/
+
+unsigned long vg_test_and_clear_interrupt (void)
+{
+ unsigned long irq_enable;
+ unsigned long lock;
+
+ irq_enable = READ_REG32 (DC3_IRQ);
+ lock = READ_REG32 (DC3_UNLOCK);
+
+ /* NO ACTION IF INTERRUPTS ARE MASKED */
+ /* We are assuming that a driver or application will not want to receive */
+ /* the status of the interrupt when it is masked. */
+
+ if ((irq_enable & (DC3_IRQ_MASK | DC3_VSYNC_IRQ_MASK)) == (DC3_IRQ_MASK | DC3_VSYNC_IRQ_MASK))
+ return 0;
+
+ WRITE_REG32 (DC3_UNLOCK, DC3_UNLOCK_VALUE);
+ WRITE_REG32 (DC3_IRQ, irq_enable);
+ WRITE_REG32 (DC3_UNLOCK, lock);
+
+ return (irq_enable & (DC3_IRQ_STATUS | DC3_VSYNC_IRQ_STATUS));
+}
+
+/*---------------------------------------------------------------------------
+ * vg_test_flip_status
+ *
+ * This routine tests if a new display offset has been latched.
+ *---------------------------------------------------------------------------*/
+
+unsigned long vg_test_flip_status (void)
+{
+ return (READ_REG32 (DC3_LINE_CNT_STATUS) & DC3_LNCNT_FLIP);
+}
+
+/*---------------------------------------------------------------------------
+ * vg_save_state
+ *
+ * This routine saves all persistent VG state information.
+ *---------------------------------------------------------------------------*/
+
+int vg_save_state (VG_SAVE_RESTORE *vg_state)
+{
+ Q_WORD msr_value;
+ unsigned long irqfilt;
+ unsigned long offset, i;
+ unsigned long lock;
+
+ /* READ ALL CURRENT REGISTER SETTINGS */
+
+ vg_state->unlock = READ_REG32 (DC3_UNLOCK);
+ vg_state->gcfg = READ_REG32 (DC3_GENERAL_CFG);
+ vg_state->dcfg = READ_REG32 (DC3_DISPLAY_CFG);
+ vg_state->arb_cfg = READ_REG32 (DC3_ARB_CFG);
+ vg_state->fb_offset = READ_REG32 (DC3_FB_ST_OFFSET);
+ vg_state->cb_offset = READ_REG32 (DC3_CB_ST_OFFSET);
+ vg_state->cursor_offset = READ_REG32 (DC3_CURS_ST_OFFSET);
+ vg_state->video_y_offset = READ_REG32 (DC3_VID_Y_ST_OFFSET);
+ vg_state->video_u_offset = READ_REG32 (DC3_VID_U_ST_OFFSET);
+ vg_state->video_v_offset = READ_REG32 (DC3_VID_V_ST_OFFSET);
+ vg_state->dv_top = READ_REG32 (DC3_DV_TOP);
+ vg_state->line_size = READ_REG32 (DC3_LINE_SIZE);
+ vg_state->gfx_pitch = READ_REG32 (DC3_GFX_PITCH);
+ vg_state->video_yuv_pitch = READ_REG32 (DC3_VID_YUV_PITCH);
+ vg_state->h_active = READ_REG32 (DC3_H_ACTIVE_TIMING);
+ vg_state->h_blank = READ_REG32 (DC3_H_BLANK_TIMING);
+ vg_state->h_sync = READ_REG32 (DC3_H_SYNC_TIMING);
+ vg_state->v_active = READ_REG32 (DC3_V_ACTIVE_TIMING);
+ vg_state->v_blank = READ_REG32 (DC3_V_BLANK_TIMING);
+ vg_state->v_sync = READ_REG32 (DC3_V_SYNC_TIMING);
+ vg_state->fb_active = READ_REG32 (DC3_FB_ACTIVE);
+ vg_state->cursor_x = READ_REG32 (DC3_CURSOR_X);
+ vg_state->cursor_y = READ_REG32 (DC3_CURSOR_Y);
+ vg_state->vid_ds_delta = READ_REG32 (DC3_VID_DS_DELTA);
+ vg_state->fb_base = READ_REG32 (DC3_PHY_MEM_OFFSET);
+ vg_state->dv_ctl = READ_REG32 (DC3_DV_CTL);
+ vg_state->gfx_scale = READ_REG32 (DC3_GFX_SCALE);
+ vg_state->irq_ctl = READ_REG32 (DC3_IRQ_FILT_CTL);
+ vg_state->vbi_even_ctl = READ_REG32 (DC3_VBI_EVEN_CTL);
+ vg_state->vbi_odd_ctl = READ_REG32 (DC3_VBI_ODD_CTL);
+ vg_state->vbi_hor_ctl = READ_REG32 (DC3_VBI_HOR);
+ vg_state->vbi_odd_line_enable = READ_REG32 (DC3_VBI_LN_ODD);
+ vg_state->vbi_even_line_enable = READ_REG32 (DC3_VBI_LN_EVEN);
+ vg_state->vbi_pitch = READ_REG32 (DC3_VBI_PITCH);
+ vg_state->color_key = READ_REG32 (DC3_COLOR_KEY);
+ vg_state->color_key_mask = READ_REG32 (DC3_COLOR_MASK);
+ vg_state->color_key_x = READ_REG32 (DC3_CLR_KEY_X);
+ vg_state->color_key_y = READ_REG32 (DC3_CLR_KEY_Y);
+ vg_state->irq = READ_REG32 (DC3_IRQ);
+ vg_state->genlk_ctl = READ_REG32 (DC3_GENLK_CTL);
+ vg_state->vid_y_even_offset = READ_REG32 (DC3_VID_EVEN_Y_ST_OFFSET);
+ vg_state->vid_u_even_offset = READ_REG32 (DC3_VID_EVEN_U_ST_OFFSET);
+ vg_state->vid_v_even_offset = READ_REG32 (DC3_VID_EVEN_V_ST_OFFSET);
+ vg_state->vactive_even = READ_REG32 (DC3_V_ACTIVE_EVEN);
+ vg_state->vblank_even = READ_REG32 (DC3_V_BLANK_EVEN);
+ vg_state->vsync_even = READ_REG32 (DC3_V_SYNC_EVEN);
+
+ /* READ THE CURRENT PALETTE */
+
+ lock = READ_REG32 (DC3_UNLOCK);
+ WRITE_REG32 (DC3_UNLOCK, DC3_UNLOCK_VALUE);
+ WRITE_REG32 (DC3_PAL_ADDRESS, 0);
+ for (i = 0; i < 261; i++)
+ vg_state->palette[i] = READ_REG32 (DC3_PAL_DATA);
+
+ /* READ THE CURRENT FILTER COEFFICIENTS */
+
+ /* ENABLE ACCESS TO THE HORIZONTAL COEFFICIENTS */
+
+ irqfilt = READ_REG32 (DC3_IRQ_FILT_CTL);
+ irqfilt |= DC3_IRQFILT_H_FILT_SEL;
+
+ /* READ HORIZONTAL COEFFICIENTS */
+
+ for (i = 0; i < 256; i++)
+ {
+ WRITE_REG32 (DC3_IRQ_FILT_CTL, ((irqfilt & 0xFFFFFF00L) | i));
+
+ vg_state->h_coeff[(i << 1)] = READ_REG32 (DC3_FILT_COEFF1);
+ vg_state->h_coeff[(i << 1) + 1] = READ_REG32 (DC3_FILT_COEFF2);
+ }
+
+ /* ENABLE ACCESS TO THE VERTICAL COEFFICIENTS */
+
+ irqfilt &= ~DC3_IRQFILT_H_FILT_SEL;
+
+ /* READ COEFFICIENTS */
+
+ for (i = 0; i < 256; i++)
+ {
+ WRITE_REG32 (DC3_IRQ_FILT_CTL, ((irqfilt & 0xFFFFFF00L) | i));
+
+ vg_state->v_coeff[i] = READ_REG32 (DC3_FILT_COEFF1);
+ }
+
+ /* READ THE CURSOR DATA */
+
+ offset = READ_REG32 (DC3_CURS_ST_OFFSET) & 0x0FFFFFFF;
+ for (i = 0; i < 3072; i++)
+ vg_state->cursor_data[i] = READ_FB32 (offset + (i << 2));
+
+ /* READ THE CURRENT PLL */
+
+ msr_read64 (MSR_DEVICE_GEODELX_GLCP, GLCP_DOTPLL, &msr_value);
+
+ vg_state->pll_flags = 0;
+ for (i = 0; i < NUM_CIMARRON_PLL_FREQUENCIES; i++)
+ {
+ if (CimarronPLLFrequencies[i].pll_value == (msr_value.high & 0x7FFF))
+ {
+ vg_state->dot_pll = CimarronPLLFrequencies[i].frequency;
+ break;
+ }
+ }
+
+ if (i == NUM_CIMARRON_PLL_FREQUENCIES)
+ {
+ /* NO MATCH */
+ /* Enter the frequency as a manual frequency. */
+
+ vg_state->dot_pll = msr_value.high;
+ vg_state->pll_flags |= VG_PLL_MANUAL;
+ }
+ if (msr_value.low & GLCP_DOTPLL_HALFPIX)
+ vg_state->pll_flags |= VG_PLL_DIVIDE_BY_2;
+ if (msr_value.low & GLCP_DOTPLL_BYPASS)
+ vg_state->pll_flags |= VG_PLL_BYPASS;
+ if (msr_value.high & GLCP_DOTPLL_DIV4)
+ vg_state->pll_flags |= VG_PLL_DIVIDE_BY_4;
+ if (msr_value.high & GLCP_DOTPLL_VIPCLK)
+ vg_state->pll_flags |= VG_PLL_VIP_CLOCK;
+
+ /* READ ALL VG MSRS */
+
+ msr_read64 (MSR_DEVICE_GEODELX_VG, MSR_GEODELINK_CAP, &(vg_state->msr_cap));
+ msr_read64 (MSR_DEVICE_GEODELX_VG, MSR_GEODELINK_CONFIG, &(vg_state->msr_config));
+ msr_read64 (MSR_DEVICE_GEODELX_VG, MSR_GEODELINK_SMI, &(vg_state->msr_smi));
+ msr_read64 (MSR_DEVICE_GEODELX_VG, MSR_GEODELINK_ERROR, &(vg_state->msr_error));
+ msr_read64 (MSR_DEVICE_GEODELX_VG, MSR_GEODELINK_PM, &(vg_state->msr_pm));
+ msr_read64 (MSR_DEVICE_GEODELX_VG, MSR_GEODELINK_DIAG, &(vg_state->msr_diag));
+ msr_read64 (MSR_DEVICE_GEODELX_VG, DC3_SPARE_MSR, &(vg_state->msr_spare));
+ msr_read64 (MSR_DEVICE_GEODELX_VG, DC3_RAM_CTL, &(vg_state->msr_ram_ctl));
+
+ WRITE_REG32 (DC3_UNLOCK, lock);
+
+ return CIM_STATUS_OK;
+}
+
+/*---------------------------------------------------------------------------
+ * vg_restore_state
+ *
+ * This routine restores all persistent VG state information.
+ *---------------------------------------------------------------------------*/
+
+int vg_restore_state (VG_SAVE_RESTORE *vg_state)
+{
+ unsigned long irqfilt, i;
+ unsigned long memoffset;
+
+ /* TEMPORARILY UNLOCK ALL REGISTERS */
+
+ WRITE_REG32 (DC3_UNLOCK, DC3_UNLOCK_VALUE);
+
+ /* RESTORE THE FRAME BUFFER OFFSET */
+
+ WRITE_REG32 (DC3_PHY_MEM_OFFSET, vg_state->fb_base);
+
+ /* BLANK GCFG AND DCFG */
+
+ WRITE_REG32 (DC3_GENERAL_CFG, 0);
+ WRITE_REG32 (DC3_DISPLAY_CFG, 0);
+
+ /* RESTORE ALL REGISTERS */
+
+ WRITE_REG32 (DC3_ARB_CFG, vg_state->arb_cfg);
+ WRITE_REG32 (DC3_FB_ST_OFFSET, vg_state->fb_offset);
+ WRITE_REG32 (DC3_CB_ST_OFFSET, vg_state->cb_offset);
+ WRITE_REG32 (DC3_CURS_ST_OFFSET, vg_state->cursor_offset);
+ WRITE_REG32 (DC3_VID_Y_ST_OFFSET, vg_state->video_y_offset);
+ WRITE_REG32 (DC3_VID_U_ST_OFFSET, vg_state->video_u_offset);
+ WRITE_REG32 (DC3_VID_V_ST_OFFSET, vg_state->video_v_offset);
+ WRITE_REG32 (DC3_DV_TOP, vg_state->dv_top);
+ WRITE_REG32 (DC3_LINE_SIZE, vg_state->line_size);
+ WRITE_REG32 (DC3_GFX_PITCH, vg_state->gfx_pitch);
+ WRITE_REG32 (DC3_VID_YUV_PITCH, vg_state->video_yuv_pitch);
+ WRITE_REG32 (DC3_H_ACTIVE_TIMING, vg_state->h_active);
+ WRITE_REG32 (DC3_H_BLANK_TIMING, vg_state->h_blank);
+ WRITE_REG32 (DC3_H_SYNC_TIMING, vg_state->h_sync);
+ WRITE_REG32 (DC3_V_ACTIVE_TIMING, vg_state->v_active);
+ WRITE_REG32 (DC3_V_BLANK_TIMING, vg_state->v_blank);
+ WRITE_REG32 (DC3_V_SYNC_TIMING, vg_state->v_sync);
+ WRITE_REG32 (DC3_FB_ACTIVE, vg_state->fb_active);
+ WRITE_REG32 (DC3_CURSOR_X, vg_state->cursor_x);
+ WRITE_REG32 (DC3_CURSOR_Y, vg_state->cursor_y);
+ WRITE_REG32 (DC3_VID_DS_DELTA, vg_state->vid_ds_delta);
+ WRITE_REG32 (DC3_PHY_MEM_OFFSET, vg_state->fb_base);
+ WRITE_REG32 (DC3_DV_CTL, vg_state->dv_ctl | 0x00000001);
+ WRITE_REG32 (DC3_GFX_SCALE, vg_state->gfx_scale);
+ WRITE_REG32 (DC3_IRQ_FILT_CTL, vg_state->irq_ctl);
+ WRITE_REG32 (DC3_VBI_EVEN_CTL, vg_state->vbi_even_ctl);
+ WRITE_REG32 (DC3_VBI_ODD_CTL, vg_state->vbi_odd_ctl);
+ WRITE_REG32 (DC3_VBI_HOR, vg_state->vbi_hor_ctl);
+ WRITE_REG32 (DC3_VBI_LN_ODD, vg_state->vbi_odd_line_enable);
+ WRITE_REG32 (DC3_VBI_LN_EVEN, vg_state->vbi_even_line_enable);
+ WRITE_REG32 (DC3_VBI_PITCH, vg_state->vbi_pitch);
+ WRITE_REG32 (DC3_COLOR_KEY, vg_state->color_key);
+ WRITE_REG32 (DC3_COLOR_MASK, vg_state->color_key_mask);
+ WRITE_REG32 (DC3_CLR_KEY_X, vg_state->color_key_x);
+ WRITE_REG32 (DC3_CLR_KEY_Y, vg_state->color_key_y);
+ WRITE_REG32 (DC3_IRQ, vg_state->irq);
+ WRITE_REG32 (DC3_GENLK_CTL, vg_state->genlk_ctl);
+ WRITE_REG32 (DC3_VID_EVEN_Y_ST_OFFSET, vg_state->vid_y_even_offset);
+ WRITE_REG32 (DC3_VID_EVEN_U_ST_OFFSET, vg_state->vid_u_even_offset);
+ WRITE_REG32 (DC3_VID_EVEN_V_ST_OFFSET, vg_state->vid_v_even_offset);
+ WRITE_REG32 (DC3_V_ACTIVE_EVEN, vg_state->vactive_even);
+ WRITE_REG32 (DC3_V_BLANK_EVEN, vg_state->vblank_even);
+ WRITE_REG32 (DC3_V_SYNC_EVEN, vg_state->vsync_even);
+
+ /* RESTORE THE PALETTE */
+
+ WRITE_REG32 (DC3_PAL_ADDRESS, 0);
+ for (i = 0; i < 261; i++)
+ WRITE_REG32 (DC3_PAL_DATA, vg_state->palette[i]);
+
+ /* RESTORE THE HORIZONTAL FILTER COEFFICIENTS */
+
+ irqfilt = READ_REG32 (DC3_IRQ_FILT_CTL);
+ irqfilt |= DC3_IRQFILT_H_FILT_SEL;
+
+ for (i = 0; i < 256; i++)
+ {
+ WRITE_REG32 (DC3_IRQ_FILT_CTL, ((irqfilt & 0xFFFFFF00L) | i));
+ WRITE_REG32 (DC3_FILT_COEFF1, vg_state->h_coeff[(i << 1)]);
+ WRITE_REG32 (DC3_FILT_COEFF2, vg_state->h_coeff[(i << 1) + 1]);
+ }
+
+ /* RESTORE VERTICAL COEFFICIENTS */
+
+ irqfilt &= ~DC3_IRQFILT_H_FILT_SEL;
+
+ for (i = 0; i < 256; i++)
+ {
+ WRITE_REG32 (DC3_IRQ_FILT_CTL, ((irqfilt & 0xFFFFFF00L) | i));
+ WRITE_REG32 (DC3_FILT_COEFF1, vg_state->v_coeff[i]);
+ }
+
+ /* RESTORE THE CURSOR DATA */
+
+ memoffset = READ_REG32 (DC3_CURS_ST_OFFSET) & 0x0FFFFFFF;
+ WRITE_FB_STRING32 (memoffset, (unsigned char *)&(vg_state->cursor_data[0]), 3072);
+
+ /* RESTORE THE PLL */
+ /* Use a common routine to use common code to poll for lock bit */
+
+ vg_set_clock_frequency (vg_state->dot_pll, vg_state->pll_flags);
+
+ /* RESTORE ALL VG MSRS */
+
+ msr_write64 (MSR_DEVICE_GEODELX_VG, MSR_GEODELINK_CAP, &(vg_state->msr_cap));
+ msr_write64 (MSR_DEVICE_GEODELX_VG, MSR_GEODELINK_CONFIG, &(vg_state->msr_config));
+ msr_write64 (MSR_DEVICE_GEODELX_VG, MSR_GEODELINK_SMI, &(vg_state->msr_smi));
+ msr_write64 (MSR_DEVICE_GEODELX_VG, MSR_GEODELINK_ERROR, &(vg_state->msr_error));
+ msr_write64 (MSR_DEVICE_GEODELX_VG, MSR_GEODELINK_PM, &(vg_state->msr_pm));
+ msr_write64 (MSR_DEVICE_GEODELX_VG, MSR_GEODELINK_DIAG, &(vg_state->msr_diag));
+ msr_write64 (MSR_DEVICE_GEODELX_VG, DC3_SPARE_MSR, &(vg_state->msr_spare));
+ msr_write64 (MSR_DEVICE_GEODELX_VG, DC3_RAM_CTL, &(vg_state->msr_ram_ctl));
+
+ /* NOW RESTORE GCFG AND DCFG */
+
+ WRITE_REG32 (DC3_DISPLAY_CFG, vg_state->dcfg);
+ WRITE_REG32 (DC3_GENERAL_CFG, vg_state->gcfg);
+
+ /* FINALLY RESTORE UNLOCK */
+
+ WRITE_REG32 (DC3_UNLOCK, vg_state->unlock);
+
+ return CIM_STATUS_OK;
+}
+
+/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ * CIMARRON VG READ ROUTINES
+ * These routines are included for use in diagnostics or when debugging. They
+ * can be optionally excluded from a project.
+ *+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
+
+#if CIMARRON_INCLUDE_VG_READ_ROUTINES
+
+/*---------------------------------------------------------------------------
+ * vg_read_graphics_crc
+ *
+ * This routine reads the Cyclic Redundancy Check (CRC) value for the graphics
+ * frame.
+ *---------------------------------------------------------------------------*/
+
+unsigned long vg_read_graphics_crc (int crc_source)
+{
+ unsigned long gcfg, unlock;
+ unsigned long crc, vbi_even;
+ unsigned long interlaced;
+ unsigned long line, field;
+
+ if (!(READ_REG32 (DC3_DISPLAY_CFG) & DC3_DCFG_TGEN))
+ return 0xFFFFFFFF;
+
+ unlock = READ_REG32 (DC3_UNLOCK);
+ gcfg = READ_REG32 (DC3_GENERAL_CFG);
+ vbi_even = READ_REG32 (DC3_VBI_EVEN_CTL);
+
+ vbi_even &= ~DC3_VBI_EVEN_ENABLE_CRC;
+
+ gcfg |= DC3_GCFG_SGRE | DC3_GCFG_CRC_MODE;
+ gcfg &= ~(DC3_GCFG_SGFR | DC3_GCFG_SIG_SEL | DC3_GCFG_FILT_SIG_SEL);
+
+ switch (crc_source)
+ {
+ case VG_CRC_SOURCE_PREFILTER_EVEN:
+ case VG_CRC_SOURCE_PREFILTER: gcfg |= DC3_GCFG_SIG_SEL; break;
+ case VG_CRC_SOURCE_PREFLICKER:
+ case VG_CRC_SOURCE_PREFLICKER_EVEN: gcfg |= DC3_GCFG_FILT_SIG_SEL; break;
+ case VG_CRC_SOURCE_POSTFLICKER:
+ case VG_CRC_SOURCE_POSTFLICKER_EVEN: /* NO WORK */ break;
+
+ default:
+ return 0xFFFFFFFF;
+ }
+
+ if (crc_source & VG_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 & VG_CRC_SOURCE_EVEN)
+ return 0xFFFFFFFF;
+ }
+
+ WRITE_REG32 (DC3_UNLOCK, DC3_UNLOCK_VALUE);
+ WRITE_REG32 (DC3_VBI_EVEN_CTL, vbi_even);
+ WRITE_REG32 (DC3_GENERAL_CFG, gcfg & ~DC3_GCFG_SIGE);
+ WRITE_REG32 (DC3_GENERAL_CFG, gcfg | DC3_GCFG_SIGE);
+
+ /* WAIT FOR THE CRC TO BE COMPLETED */
+
+ while (!(READ_REG32 (DC3_LINE_CNT_STATUS) & DC3_LNCNT_SIGC))
+ ;
+
+ /* READ THE COMPLETED CRC */
+
+ crc = READ_REG32 (DC3_PAL_DATA);
+
+ /* RESTORE THE PALETTE SETTINGS */
+
+ gcfg &= ~DC3_GCFG_SGRE;
+ WRITE_REG32 (DC3_GENERAL_CFG, gcfg);
+ WRITE_REG32 (DC3_UNLOCK, unlock);
+
+ return crc;
+}
+
+/*---------------------------------------------------------------------------
+ * vg_read_window_crc
+ *
+ * This routine reads the Cyclic Redundancy Check (CRC) value for a sub-section
+ * of the frame.
+ *---------------------------------------------------------------------------*/
+
+unsigned long vg_read_window_crc (int crc_source, unsigned long x, unsigned long y,
+ unsigned long width, unsigned long height)
+{
+ Q_WORD msr_value;
+ unsigned long crc = 0;
+ unsigned long hactive, hblankstart;
+ unsigned long htotal, hblankend;
+ unsigned long line, field;
+ unsigned long diag;
+
+ hactive = ((READ_REG32 (DC3_H_ACTIVE_TIMING)) & 0xFFF) + 1;
+ hblankstart = ((READ_REG32 (DC3_H_BLANK_TIMING)) & 0xFFF) + 1;
+ htotal = ((READ_REG32 (DC3_H_ACTIVE_TIMING) >> 16) & 0xFFF) + 1;
+ hblankend = ((READ_REG32 (DC3_H_BLANK_TIMING) >> 16) & 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);
+
+ if ((x == 0 && width == 1) || x == 1)
+ {
+ /* SPECIAL CASE FOR X == 0 */
+ /* The comparator output is a clock late in the MCP, so we cannot */
+ /* easily catch the first pixel. If the first pixel is desired, */
+ /* we will insert a special state machine to CRC just the first */
+ /* pixel. */
+
+ /* N2 - DISPE HIGH AND Y == 1 */
+ /* Goto state YState = 2 */
+
+ msr_value.high = 0x00000002;
+ msr_value.low = 0x00000C00;
+ msr_write64 (MSR_DEVICE_GEODELX_GLCP, GLCP_SETN0CTL + 2, &msr_value);
+
+ /* M3 - DISPE HIGH AND Y == 0 */
+ /* Goto YState = 1 */
+
+ msr_value.high = 0x00000002;
+ msr_value.low = 0x00000A00;
+ msr_write64 (MSR_DEVICE_GEODELX_GLCP, GLCP_SETM0CTL + 3, &msr_value);
+
+ /* N3 - DISPE LOW */
+ /* Goto YState = 0 */
+
+ msr_value.high = 0x00080000;
+ msr_value.low = 0x00000000;
+ msr_write64 (MSR_DEVICE_GEODELX_GLCP, GLCP_SETN0CTL + 3, &msr_value);
+
+ /* Y0 -> Y1 (SET M3) */
+
+ msr_value.high = 0x00000000;
+ msr_value.low = 0x0000C000;
+ msr_write64 (MSR_DEVICE_GEODELX_GLCP, GLCP_ACTION0 + 18, &msr_value);
+
+ /* Y1 -> Y0 (SET N3) */
+
+ msr_value.low = 0x0000A000;
+ msr_write64 (MSR_DEVICE_GEODELX_GLCP, GLCP_ACTION0 + 17, &msr_value);
+
+ /* Y1 -> Y2 (SET N2) */
+
+ msr_value.low = 0x00000A00;
+ msr_write64 (MSR_DEVICE_GEODELX_GLCP, GLCP_ACTION0 + 19, &msr_value);
+
+ /* N5 (XSTATE = 10 && CMP2 <= V. COUNTER <= CMP3) && DISPE && Y == 0 */
+ /* CRC into REGB */
+
+ msr_value.high = 0x00000002;
+ msr_value.low = 0x10800B20;
+ msr_write64 (MSR_DEVICE_GEODELX_GLCP, GLCP_SETN0CTL + 5, &msr_value);
+
+ /* N6 (XSTATE = 10 && CMP2 <= V. COUNTER <= CMP3) && DISPE && Y == 1 */
+ /* CRC into REGB */
+
+ msr_value.high = 0x00000002;
+ msr_value.low = 0x10800D20;
+ msr_write64 (MSR_DEVICE_GEODELX_GLCP, GLCP_SETN0CTL + 6, &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 DISPE HIGH) */
+ /* Increment H. Counter */
+ /* Note: DispE = H4 */
+
+ msr_value.high = 0x00000002;
+ 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) && DISPE */
+ /* CRC into REGB */
+
+ msr_value.high = 0x00000002;
+ msr_value.low = 0x10C20120;
+ msr_write64 (MSR_DEVICE_GEODELX_GLCP, GLCP_SETN0CTL + 4, &msr_value);
+
+ /* COMPARATOR 0 VALUE */
+ /* We subtract 1 to account for a pipeline delay in the GLCP. */
+ /* When the x coordinate is 0, we must play a special game. */
+ /* If the width is exactly 1, we will set up a state machine */
+ /* to only CRC the first pixel. Otherwise, we will set it */
+ /* as an OR combination of a state that CRCs the first pixel */
+ /* and a state that CRCs 1 clock delayed width (width - 1) */
+
+ msr_value.high = 0;
+ if (x > 1) msr_value.low = (x - 1) & 0xFFFF;
+ else msr_value.low = x;
+ msr_write64 (MSR_DEVICE_GEODELX_GLCP, GLCP_CMPVAL0, &msr_value);
+
+ /* COMPARATOR 1 VALUE */
+
+ if ((x == 0 || x == 1) && width > 1) msr_value.low += width - 2;
+ else msr_value.low += width - 1;
+ msr_write64 (MSR_DEVICE_GEODELX_GLCP, GLCP_CMPVAL0 + 2, &msr_value);
+
+ /* COMPARATOR 2 VALUE */
+
+ msr_value.low = y << 16;
+ msr_write64 (MSR_DEVICE_GEODELX_GLCP, GLCP_CMPVAL0 + 4, &msr_value);
+
+ /* COMPARATOR 3 VALUE */
+
+ 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 all 32 bits of data are CRCed */
+
+ msr_value.low = 0xFFFFFFFF;
+ msr_write64 (MSR_DEVICE_GEODELX_GLCP, GLCP_REGBMASK, &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 */
+ /* Increment h.counter if xstate = 10 and HSync is low. */
+
+ msr_value.low = 0x000A00A0;
+ if (x == 0 && width == 1)
+ msr_value.low = 0x00A000A0;
+ else if (x == 1 && width == 1)
+ msr_value.low = 0x0A0000A0;
+ else if (x == 1 && width > 1)
+ msr_value.low |= 0x0A000000;
+
+ 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);
+
+ /* SET YSTATE TO 0 */
+
+ msr_write64 (MSR_DEVICE_GEODELX_GLCP, GLCP_YSTATE, &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 + 20, &msr_value);
+
+ /* SET DIAG SETTINGS BASED ON DESIRED CRC */
+
+ if (crc_source == VG_CRC_SOURCE_POSTFLICKER || crc_source == VG_CRC_SOURCE_POSTFLICKER_EVEN)
+ {
+ diag = 0x80808086;
+
+ /* ENABLE HW CLOCK GATING AND SET GLCP CLOCK TO DOT CLOCK */
+
+ msr_value.high = 0;
+ 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);
+
+ /* SET REGA LIMITS */
+ /* Lower counter uses pixels/line */
+ /* Upper counter is 0xFFFF to prevent rollover. */
+
+ msr_value.low = 0xFFFF0000 | (hactive - 1);
+ if (READ_REG32 (DC3_DISPLAY_CFG) & DC3_DCFG_DCEN)
+ {
+ msr_value.low += hblankstart - hactive;
+ msr_value.low += htotal - hblankend;
+ }
+ msr_write64 (MSR_DEVICE_GEODELX_GLCP, GLCP_REGAVAL, &msr_value);
+
+ /* USE H4 FUNCTION A FOR DISPE AND H4 FUNCTION B FOR NOT DISPE */
+ /* DISPE is bit 34 */
+
+ msr_value.high = 0x00000002;
+ msr_value.low = 0x20000FF0;
+ 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 32. */
+
+ msr_value.high = 0x00000000;
+ msr_value.low = 0x002055AA;
+ msr_write64 (MSR_DEVICE_GEODELX_GLCP, GLCP_H0CTL + 3, &msr_value);
+ }
+ else if (crc_source == VG_CRC_SOURCE_PREFLICKER || crc_source == VG_CRC_SOURCE_PREFLICKER_EVEN)
+ {
+ diag = 0x801F8032;
+
+ /* ENABLE HW CLOCK GATING AND SET GLCP CLOCK TO GEODELINK CLOCK */
+
+ msr_value.high = 0;
+ 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 = 2;
+ msr_write64 (MSR_DEVICE_GEODELX_GLCP, GLCP_DBGCLKCTL, &msr_value);
+
+ /* SET REGA LIMITS */
+ /* Lower counter uses pixels/line */
+ /* Upper counter is 0xFFFF to prevent rollover. */
+
+ msr_value.low = 0xFFFF0000 | (hactive - 1);
+ msr_write64 (MSR_DEVICE_GEODELX_GLCP, GLCP_REGAVAL, &msr_value);
+
+ /* USE H4 FUNCTION A FOR DISPE AND H4 FUNCTION B FOR NOT DISPE */
+ /* DISPE is bit 47 */
+
+ msr_value.high = 0x00000002;
+ msr_value.low = 0xF0000FF0;
+ 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 45. */
+
+ msr_value.high = 0x00000000;
+ msr_value.low = 0x002D55AA;
+ msr_write64 (MSR_DEVICE_GEODELX_GLCP, GLCP_H0CTL + 3, &msr_value);
+ }
+ else
+ {
+ /* PREFILTER CRC */
+
+ diag = 0x80138048;
+ msr_write64 (MSR_DEVICE_GEODELX_VG, MSR_GEODELINK_DIAG, &msr_value);
+
+ /* ENABLE HW CLOCK GATING AND SET GLCP CLOCK TO GEODELINK CLOCK */
+
+ msr_value.high = 0;
+ 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 = 2;
+ msr_write64 (MSR_DEVICE_GEODELX_GLCP, GLCP_DBGCLKCTL, &msr_value);
+
+ /* SET REGA LIMITS */
+ /* Lower counter uses pixels/line */
+ /* Upper counter is 0xFFFF to prevent rollover. */
+ /* Note that we are assuming that the number of */
+ /* source pixels is specified in the FB_ACTIVE register */
+
+ msr_value.low = 0xFFFF0000 | ((READ_REG32 (DC3_FB_ACTIVE) >> 16) & 0xFFF);
+ msr_write64 (MSR_DEVICE_GEODELX_GLCP, GLCP_REGAVAL, &msr_value);
+
+ /* USE H4 FUNCTION A FOR DISPE AND H4 FUNCTION B FOR NOT DISPE */
+ /* DISPE is bit 55 */
+
+ msr_value.high = 0x00000003;
+ msr_value.low = 0x70000FF0;
+ 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 53. */
+
+ msr_value.high = 0x00000000;
+ msr_value.low = 0x003555AA;
+ msr_write64 (MSR_DEVICE_GEODELX_GLCP, GLCP_H0CTL + 3, &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 (crc_source & VG_CRC_SOURCE_EVEN) field = 0;
+ else field = DC3_LNCNT_EVEN_FIELD;
+
+ if (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) < 1 ||
+ ((line & DC3_LNCNT_V_LINE_CNT) >> 16) > 5);
+ }
+ else
+ {
+ /* NON-INTERLACED - EVEN FIELD CRCS ARE INVALID */
+
+ if (crc_source & VG_CRC_SOURCE_EVEN)
+ return 0xFFFFFFFF;
+ }
+
+ /* UPDATE VG DIAG OUTPUT */
+
+ msr_value.high = 0;
+ msr_value.low = diag;
+ msr_write64 (MSR_DEVICE_GEODELX_VG, 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 VG DIAG BUS OUTPUTS */
+
+ msr_value.low = 0x00000000;
+ msr_value.high = 0x00000000;
+ msr_write64 (MSR_DEVICE_GEODELX_VG, MSR_GEODELINK_DIAG, &msr_value);
+
+ /* DISABLE GLCP ACTIONS */
+
+ msr_write64 (MSR_DEVICE_GEODELX_GLCP, GLCP_DIAGCTL, &msr_value);
+
+ return crc;
+}
+
+/*---------------------------------------------------------------------------
+ * vg_get_scaler_filter_coefficients
+ *
+ * This routine gets the vertical and horizontal filter coefficients for
+ * graphics scaling. The coefficients are sign extended to 32-bit values.
+ *---------------------------------------------------------------------------*/
+
+int vg_get_scaler_filter_coefficients (long h_taps[][5], long v_taps[][3])
+{
+ unsigned long irqfilt, i;
+ unsigned long temp;
+ long coeff0, coeff1, coeff2;
+ unsigned long lock;
+
+ /* ENABLE ACCESS TO THE HORIZONTAL COEFFICIENTS */
+
+ lock = READ_REG32 (DC3_UNLOCK);
+ irqfilt = READ_REG32 (DC3_IRQ_FILT_CTL);
+ irqfilt |= DC3_IRQFILT_H_FILT_SEL;
+
+ /* WRITE COEFFICIENTS */
+ /* Coefficient indexes do not auto-increment, so we must */
+ /* write the address for every phase */
+
+ WRITE_REG32 (DC3_UNLOCK, DC3_UNLOCK_VALUE);
+
+ for (i = 0; i < 256; i++)
+ {
+ WRITE_REG32 (DC3_IRQ_FILT_CTL, ((irqfilt & 0xFFFFFF00L) | i));
+
+ temp = READ_REG32 (DC3_FILT_COEFF1);
+ coeff0 = (temp & 0x3FF);
+ coeff1 = (temp >> 10) & 0x3FF;
+ coeff2 = (temp >> 20) & 0x3FF;
+
+ h_taps[i][0] = (coeff0 << 22) >> 22;
+ h_taps[i][1] = (coeff1 << 22) >> 22;
+ h_taps[i][2] = (coeff2 << 22) >> 22;
+
+ temp = READ_REG32 (DC3_FILT_COEFF2);
+ coeff0 = (temp & 0x3FF);
+ coeff1 = (temp >> 10) & 0x3FF;
+
+ h_taps[i][3] = (coeff0 << 22) >> 22;
+ h_taps[i][4] = (coeff1 << 22) >> 22;
+ }
+
+ /* ENABLE ACCESS TO THE VERTICAL COEFFICIENTS */
+
+ irqfilt &= ~DC3_IRQFILT_H_FILT_SEL;
+
+ /* WRITE COEFFICIENTS */
+
+ for (i = 0; i < 256; i++)
+ {
+ WRITE_REG32 (DC3_IRQ_FILT_CTL, ((irqfilt & 0xFFFFFF00L) | i));
+
+ temp = READ_REG32 (DC3_FILT_COEFF1);
+ coeff0 = (temp & 0x3FF);
+ coeff1 = (temp >> 10) & 0x3FF;
+ coeff2 = (temp >> 20) & 0x3FF;
+
+ v_taps[i][0] = (coeff0 << 22) >> 22;
+ v_taps[i][1] = (coeff1 << 22) >> 22;
+ v_taps[i][2] = (coeff2 << 22) >> 22;
+ }
+
+ WRITE_REG32 (DC3_UNLOCK, lock);
+
+ return CIM_STATUS_OK;
+}
+
+/*---------------------------------------------------------------------------
+ * vg_get_flicker_filter_configuration
+ *
+ * This routine returns the current VG flicker filter configuration.
+ *---------------------------------------------------------------------------*/
+
+int vg_get_flicker_filter_configuration (unsigned long *strength, int *flicker_alpha)
+{
+ unsigned long genlk_ctl;
+
+ if (!strength || !flicker_alpha)
+ return CIM_STATUS_INVALIDPARAMS;
+
+ genlk_ctl = READ_REG32 (DC3_GENLK_CTL);
+ *strength = genlk_ctl & DC3_GC_FLICKER_FILTER_MASK;
+ if (genlk_ctl & DC3_GC_ALPHA_FLICK_ENABLE)
+ *flicker_alpha = 1;
+ else
+ *flicker_alpha = 0;
+
+ return CIM_STATUS_OK;
+}
+
+/*---------------------------------------------------------------------------
+ * vg_get_display_pitch
+ *
+ * This routine returns the current stride between successive lines of frame
+ * buffer data.
+ *---------------------------------------------------------------------------*/
+
+unsigned long vg_get_display_pitch (void)
+{
+ return ((READ_REG32 (DC3_GFX_PITCH) & 0x0000FFFF) << 3);
+}
+
+/*---------------------------------------------------------------------------
+ * vg_get_frame_buffer_line_size
+ *
+ * This routine returns the current size in bytes of one line of frame buffer
+ * data.
+ *---------------------------------------------------------------------------*/
+
+unsigned long vg_get_frame_buffer_line_size (void)
+{
+ return ((READ_REG32 (DC3_LINE_SIZE) & 0x3FF) << 3);
+}
+
+/*---------------------------------------------------------------------------
+ * vg_get_current_vline
+ *
+ * This routine returns the number of the current line that is being displayed
+ * by the display controller.
+ *---------------------------------------------------------------------------*/
+
+unsigned long vg_get_current_vline (void)
+{
+ unsigned long current_line;
+
+ /* READ THE REGISTER TWICE TO ENSURE THAT THE VALUE IS NOT TRANSITIONING */
+
+ do
+ {
+ current_line = READ_REG32(DC3_LINE_CNT_STATUS) & DC3_LNCNT_V_LINE_CNT;
+ }
+ while (current_line != (READ_REG32(DC3_LINE_CNT_STATUS) & DC3_LNCNT_V_LINE_CNT));
+
+ return (current_line >> 16);
+}
+
+/*---------------------------------------------------------------------------
+ * vg_get_display_offset
+ *
+ * This routine returns the offset into the frame buffer for the first pixel
+ * of the display.
+ *---------------------------------------------------------------------------*/
+
+unsigned long vg_get_display_offset (void)
+{
+ return (READ_REG32(DC3_FB_ST_OFFSET) & 0x0FFFFFFF);
+}
+
+/*---------------------------------------------------------------------------
+ * vg_get_cursor_info
+ *
+ * This routine returns the current settings for the hardware cursor.
+ *---------------------------------------------------------------------------*/
+
+int vg_get_cursor_info (VG_CURSOR_DATA *cursor_data)
+{
+ unsigned long temp;
+
+ /* CURSOR OFFSET */
+
+ cursor_data->cursor_offset = READ_REG32 (DC3_CURS_ST_OFFSET) & 0x0FFFFFFF;
+
+ /* CURSOR X POSITION */
+
+ temp = READ_REG32 (DC3_CURSOR_X);
+ cursor_data->cursor_x = temp & 0x7FF;
+ cursor_data->clipx = (temp >> 11) & 0x3F;
+
+ /* CURSOR Y POSITION */
+
+ temp = READ_REG32 (DC3_CURSOR_Y);
+ cursor_data->cursor_y = temp & 0x7FF;
+ cursor_data->clipy = (temp >> 11) & 0x3F;
+
+ /* CURSOR COLORS */
+
+ WRITE_REG32 (DC3_PAL_ADDRESS, 0x100);
+ cursor_data->mono_color0 = READ_REG32 (DC3_PAL_DATA);
+ cursor_data->mono_color1 = READ_REG32 (DC3_PAL_DATA);
+
+ /* CURSOR ENABLES */
+
+ temp = READ_REG32 (DC3_GENERAL_CFG);
+ if (temp & DC3_GCFG_CURE) cursor_data->enable = 1;
+ else cursor_data->enable = 0;
+ if (temp & DC3_GCFG_CLR_CUR) cursor_data->color_cursor = 1;
+ else cursor_data->color_cursor = 0;
+
+ return CIM_STATUS_OK;
+}
+
+/*-----------------------------------------------------------------------------
+ * vg_get_display_palette_entry
+ *
+ * This routine reads a single entry in the 8BPP display palette.
+ *----------------------------------------------------------------------------*/
+
+int vg_get_display_palette_entry (unsigned long index, unsigned long *entry)
+{
+ if (index > 0xFF)
+ return CIM_STATUS_INVALIDPARAMS;
+
+ WRITE_REG32 (DC3_PAL_ADDRESS, index);
+ *entry = READ_REG32 (DC3_PAL_DATA);
+
+ return CIM_STATUS_OK;
+}
+
+/*-----------------------------------------------------------------------------
+ * vg_get_border_color
+ *
+ * This routine reads the current border color for centered displays.
+ *----------------------------------------------------------------------------*/
+
+unsigned long vg_get_border_color (void)
+{
+ WRITE_REG32 (DC3_PAL_ADDRESS, 0x104);
+ return READ_REG32 (DC3_PAL_DATA);
+}
+
+/*-----------------------------------------------------------------------------
+ * vg_get_display_palette
+ *
+ * This routines reads the entire contents of the display palette into a buffer.
+ * The display palette consists of 256 X:R:G:B values.
+ *----------------------------------------------------------------------------*/
+
+int vg_get_display_palette (unsigned long *palette)
+{
+ unsigned long i;
+
+ if (palette)
+ {
+ WRITE_REG32 (DC3_PAL_ADDRESS, 0);
+ for (i = 0; i < 256; i++)
+ {
+ palette[i] = READ_REG32 (DC3_PAL_DATA);
+ }
+ return CIM_STATUS_OK;
+ }
+ return CIM_STATUS_INVALIDPARAMS;
+}
+
+/*-----------------------------------------------------------------------------
+ * vg_get_compression_info
+ *
+ * This routines reads the current status of the display compression hardware.
+ *----------------------------------------------------------------------------*/
+
+int vg_get_compression_info (VG_COMPRESSION_DATA *comp_data)
+{
+ comp_data->compression_offset = READ_REG32 (DC3_CB_ST_OFFSET) & 0x0FFFFFFF;
+ comp_data->pitch = (READ_REG32 (DC3_GFX_PITCH) >> 13) & 0x7FFF8;
+ comp_data->size = ((READ_REG32 (DC3_LINE_SIZE) >> (DC3_LINE_SIZE_CB_SHIFT - 3)) & 0x3F8) + 24;
+
+ return CIM_STATUS_OK;
+}
+
+/*-----------------------------------------------------------------------------
+ * vg_get_compression_enable
+ *
+ * This routines reads the current enable status of the display compression hardware.
+ *----------------------------------------------------------------------------*/
+
+int vg_get_compression_enable (void)
+{
+ if (READ_REG32 (DC3_GENERAL_CFG) & DC3_GCFG_CMPE)
+ return 1;
+
+ return 0;
+}
+
+/*-----------------------------------------------------------------------------
+ * vg_get_valid_bit
+ *----------------------------------------------------------------------------*/
+
+int vg_get_valid_bit (int line)
+{
+ unsigned long offset;
+ unsigned long valid;
+ unsigned long lock;
+
+ lock = READ_REG32 (DC3_UNLOCK);
+ offset = READ_REG32 (DC3_PHY_MEM_OFFSET) & 0xFF000000;
+ offset |= line;
+
+ WRITE_REG32 (DC3_UNLOCK, DC3_UNLOCK_VALUE);
+ WRITE_REG32 (DC3_PHY_MEM_OFFSET, offset);
+ WRITE_REG32 (DC3_UNLOCK, lock);
+ valid = READ_REG32 (DC3_DV_ACC) & 2;
+
+ if (valid) return 1;
+ return 0;
+}
+
+#endif
diff -Nru kernel-2.6.18geode-hurricane.orig/lib/cimarron/cim/cim_vip.c kernel-2.6.18geode-hurricane/lib/cimarron/cim/cim_vip.c
--- kernel-2.6.18geode-hurricane.orig/lib/cimarron/cim/cim_vip.c 1970-01-01 01:00:00.000000000 +0100
+++ kernel-2.6.18geode-hurricane/lib/cimarron/cim/cim_vip.c 2006-12-01 13:21:21.000000000 +0100
@@ -0,0 +1,1565 @@
+ /*
+ *
+ * Copyright (C) 2005 Advanced Micro Devices, Inc. All Rights Reserved.
+ *
+ *
+ *
+ *
+ *
+ *
+ * Cimarron VIP configuration routines.
+ *
+ *
+ */
+
+/*---------------------------------------------------------------------------
+ * vip_initialize
+ *
+ * This routine initializes the internal module state and prepares the
+ * module for subsequent VIP orientated activities.
+ *---------------------------------------------------------------------------*/
+
+int vip_initialize(VIPSETMODEBUFFER *buffer)
+{
+ unsigned long vip_control1, vip_control2, vip_control3;
+
+ if (!buffer)
+ return CIM_STATUS_INVALIDPARAMS;
+
+ vip_control1 = 0;
+ vip_control2 = 0;
+ vip_control3 = 0;
+
+ /* CONFIGURE CONTROL WORDS BASED ON MODE STRUCTURE */
+ /* Note that some of the input parameters match the register fields */
+ /* they represent. */
+
+ /* STREAM ENABLES */
+
+ vip_control1 |= buffer->stream_enables;
+
+ /* VIP CAPTURE MODE */
+
+ vip_control1 |= buffer->operating_mode;
+
+ /* HANDLE PLANAR CAPTURE */
+
+ if (buffer->flags & VIP_MODEFLAG_PLANARCAPTURE)
+ {
+ vip_control1 |= VIP_CONTROL1_PLANAR;
+
+ if (buffer->planar_capture == VIP_420CAPTURE_EVERYLINE)
+ {
+ vip_control1 |= VIP_CONTROL1_DISABLE_DECIMATION;
+ }
+ else if (buffer->planar_capture == VIP_420CAPTURE_ALTERNATINGFIELDS)
+ {
+ if (buffer->flags & VIP_MODEFLAG_PROGRESSIVE)
+ return CIM_STATUS_INVALIDPARAMS;
+
+ vip_control1 |= VIP_CONTROL1_DISABLE_DECIMATION;
+ vip_control3 |= VIP_CONTROL3_DECIMATE_EVEN;
+ }
+ else if (buffer->planar_capture != VIP_420CAPTURE_ALTERNATINGLINES)
+ return CIM_STATUS_INVALIDPARAMS;
+
+ /* CONFIGURE THE VIDEO FIFO THRESHOLD BASED ON THE FIFO DEPTH */
+
+ vip_control2 |= VIP_CONTROL2_DEFAULT_VIDTH_420 << VIP_CONTROL2_VIDTH_SHIFT;
+
+ }
+ else
+ {
+ vip_control2 |= VIP_CONTROL2_DEFAULT_VIDTH_422 << VIP_CONTROL2_VIDTH_SHIFT;
+ }
+
+ /* CONFIGURE DEFAULT ANCILARRY THRESHOLD AND VIDEO FLUSH VALUES */
+
+ vip_control2 |= VIP_CONTROL2_DEFAULT_ANCTH << VIP_CONTROL2_ANCTH_SHIFT;
+ vip_control1 |= VIP_CONTROL1_DEFAULT_ANC_FF << VIP_CONTROL1_ANC_FF_SHIFT;
+ vip_control1 |= VIP_CONTROL1_DEFAULT_VID_FF << VIP_CONTROL1_VID_FF_SHIFT;
+
+ /* PROGRAM VIP OPTIONS */
+ /* The options are sanitized based on the current configuration. */
+
+ if (buffer->flags & VIP_MODEFLAG_PROGRESSIVE)
+ vip_control1 |= VIP_CONTROL1_NON_INTERLACED;
+ else
+ {
+ if (buffer->flags & VIP_MODEFLAG_TOGGLEEACHFIELD)
+ vip_control3 |= VIP_CONTROL3_BASE_UPDATE;
+ if (buffer->flags & VIP_MODEFLAG_INVERTPOLARITY)
+ vip_control2 |= VIP_CONTROL2_INVERT_POLARITY;
+ }
+
+ if ((buffer->operating_mode == VIP_MODE_MSG ||
+ buffer->operating_mode == VIP_MODE_DATA) &&
+ (buffer->flags & VIP_MODEFLAG_FLIPMESSAGEWHENFULL))
+ {
+ vip_control1 |= VIP_CONTROL1_MSG_STRM_CTRL;
+ }
+
+ else if (buffer->operating_mode == VIP_MODE_VIP2_8BIT ||
+ buffer->operating_mode == VIP_MODE_VIP2_16BIT)
+ {
+ if (buffer->flags & VIP_MODEFLAG_ENABLEREPEATFLAG)
+ vip_control2 |= VIP_CONTROL2_REPEAT_ENABLE;
+ if (buffer->flags & VIP_MODEFLAG_INVERTTASKPOLARITY)
+ vip_control3 |= VIP_CONTROL3_TASK_POLARITY;
+ }
+
+ if (buffer->flags & VIP_MODEFLAG_DISABLEZERODETECT)
+ vip_control1 |= VIP_CONTROL1_DISABLE_ZERO_DETECT;
+ if (buffer->flags & VIP_MODEFLAG_10BITANCILLARY)
+ vip_control2 |= VIP_CONTROL2_ANC10;
+
+ /* WRITE THE CONTROL REGISTERS */
+ /* The control registers are kept 'live' to allow separate instances of */
+ /* Cimarron to control the VIP hardware. */
+
+ WRITE_VIP32 (VIP_CONTROL1, vip_control1);
+ WRITE_VIP32 (VIP_CONTROL2, vip_control2);
+ WRITE_VIP32 (VIP_CONTROL3, vip_control3);
+
+ /* CONFIGURE 601 PARAMETERS */
+
+ if (buffer->operating_mode == VIP_MODE_8BIT601 ||
+ buffer->operating_mode == VIP_MODE_16BIT601)
+ {
+ vip_update_601_params (&buffer->vip601_settings);
+ }
+
+ return CIM_STATUS_OK;
+}
+
+/*---------------------------------------------------------------------------
+ * vip_update_601_params
+ *
+ * This routine configures all aspects of 601 VIP data capture, including
+ * start and stop timings and input polarities.
+ *---------------------------------------------------------------------------*/
+
+int vip_update_601_params (VIP_601PARAMS *buffer)
+{
+ unsigned long vip_control3, vip_control1;
+
+ if (!buffer)
+ return CIM_STATUS_INVALIDPARAMS;
+
+ vip_control1 = READ_VIP32 (VIP_CONTROL3);
+ vip_control3 = READ_VIP32 (VIP_CONTROL3);
+
+ if (buffer->flags & VIP_MODEFLAG_VSYNCACTIVEHIGH) vip_control3 |= VIP_CONTROL3_VSYNC_POLARITY;
+ else vip_control3 &= ~VIP_CONTROL3_VSYNC_POLARITY;
+ if (buffer->flags & VIP_MODEFLAG_HSYNCACTIVEHIGH) vip_control3 |= VIP_CONTROL3_HSYNC_POLARITY;
+ else vip_control3 &= ~VIP_CONTROL3_HSYNC_POLARITY;
+
+ WRITE_VIP32 (VIP_CONTROL3, vip_control3);
+ WRITE_VIP32 (VIP_601_HORZ_START, buffer->horz_start);
+ WRITE_VIP32 (VIP_601_VBI_START, buffer->vbi_start);
+ WRITE_VIP32 (VIP_601_VBI_END, buffer->vbi_start + buffer->vbi_height - 1);
+ WRITE_VIP32 (VIP_601_EVEN_START_STOP,
+ buffer->vert_start_even | ((buffer->vert_start_even + buffer->even_height - 1) << 16));
+ WRITE_VIP32 (VIP_601_ODD_START_STOP,
+ buffer->vert_start_odd | ((buffer->vert_start_odd + buffer->odd_height - 1) << 16));
+ WRITE_VIP32 (VIP_ODD_FIELD_DETECT,
+ buffer->odd_detect_start | (buffer->odd_detect_end << 16));
+
+ /* SPECIAL CASE FOR HORIZONTAL DATA */
+ /* 601 horizontal parameters are based on the number of clocks and not the */
+ /* number of pixels. */
+
+ if ((vip_control1 & VIP_CONTROL1_MODE_MASK) == VIP_MODE_16BIT601)
+ WRITE_VIP32 (VIP_601_HORZ_END, buffer->horz_start + (buffer->width << 1) + 3);
+ else
+ WRITE_VIP32 (VIP_601_HORZ_END, buffer->horz_start + buffer->width + 3);
+
+ return CIM_STATUS_OK;
+}
+
+/*---------------------------------------------------------------------------
+ * vip_configure_capture_buffers
+ *
+ * This routine configures the base offsets for video, ancillary or message
+ * mode capture. The input structure can also contain multiple offsets, such
+ * that the calling application can avoid updating the structure for each flip.
+ *
+ * The new buffer addresses are written to the hardware registers although
+ * they may not be latched immediately. Calling vip_is_buffer_update_latched
+ * allows the determination of whether the update has occured.
+ *
+ * Review the Cimarron VIP API documentation to determine which buffer addresses are
+ * latched immediately.
+ *---------------------------------------------------------------------------*/
+
+int vip_configure_capture_buffers (int buffer_type, VIPINPUTBUFFER *buffer)
+{
+ VIPINPUTBUFFER_ADDR *offsets;
+ unsigned long cur_buffer = buffer->current_buffer;
+
+ if (!buffer)
+ return CIM_STATUS_INVALIDPARAMS;
+
+ if (buffer_type == VIP_BUFFER_A || buffer_type == VIP_BUFFER_601)
+ {
+ offsets = &buffer->offsets[VIP_BUFFER_TASK_A];
+
+ /* SET VIDEO PITCH */
+
+ WRITE_VIP32 (VIP_TASKA_VID_PITCH, offsets->y_pitch | (offsets->uv_pitch << 16));
+
+ /* SET BASE OFFSETS */
+
+ if (buffer->flags & VIP_INPUTFLAG_INVERTPOLARITY)
+ {
+ WRITE_VIP32 (VIP_TASKA_VID_ODD_BASE, offsets->even_base[cur_buffer]);
+ WRITE_VIP32 (VIP_TASKA_VID_EVEN_BASE, offsets->odd_base[cur_buffer]);
+ if (buffer->flags & VIP_INPUTFLAG_VBI)
+ {
+ WRITE_VIP32 (VIP_TASKA_VBI_ODD_BASE, offsets->vbi_even_base);
+ WRITE_VIP32 (VIP_TASKA_VBI_EVEN_BASE, offsets->vbi_odd_base);
+ }
+ }
+ else
+ {
+ WRITE_VIP32 (VIP_TASKA_VID_ODD_BASE, offsets->odd_base[cur_buffer]);
+ WRITE_VIP32 (VIP_TASKA_VID_EVEN_BASE, offsets->even_base[cur_buffer]);
+ if (buffer->flags & VIP_INPUTFLAG_VBI)
+ {
+ WRITE_VIP32 (VIP_TASKA_VBI_ODD_BASE, offsets->vbi_odd_base);
+ WRITE_VIP32 (VIP_TASKA_VBI_EVEN_BASE, offsets->vbi_even_base);
+ }
+ }
+
+ /* SET 4:2:0 OFFSETS */
+
+ if (buffer->flags & VIP_INPUTFLAG_PLANAR)
+ {
+ WRITE_VIP32 (VIP_TASKA_U_OFFSET, offsets->odd_uoffset);
+ WRITE_VIP32 (VIP_TASKA_V_OFFSET, offsets->odd_voffset);
+ WRITE_VIP32 (VIP_TASKA_U_EVEN_OFFSET, offsets->even_uoffset);
+ WRITE_VIP32 (VIP_TASKA_V_EVEN_OFFSET, offsets->even_voffset);
+ }
+ }
+ else if (buffer_type == VIP_BUFFER_B)
+ {
+ offsets = &buffer->offsets[VIP_BUFFER_TASK_B];
+
+ /* SET VIDEO PITCH */
+
+ WRITE_VIP32 (VIP_TASKB_VID_PITCH, offsets->y_pitch | (offsets->uv_pitch << 16));
+
+ /* SET BASE OFFSETS */
+
+ if (buffer->flags & VIP_INPUTFLAG_INVERTPOLARITY)
+ {
+ WRITE_VIP32 (VIP_TASKB_VID_ODD_BASE, offsets->even_base[cur_buffer]);
+ WRITE_VIP32 (VIP_TASKB_VID_EVEN_BASE, offsets->odd_base[cur_buffer]);
+ if (buffer->flags & VIP_INPUTFLAG_VBI)
+ {
+ WRITE_VIP32 (VIP_TASKB_VBI_ODD_BASE, offsets->vbi_even_base);
+ WRITE_VIP32 (VIP_TASKB_VBI_EVEN_BASE, offsets->vbi_odd_base);
+ }
+ }
+ else
+ {
+ WRITE_VIP32 (VIP_TASKB_VID_ODD_BASE, offsets->odd_base[cur_buffer]);
+ WRITE_VIP32 (VIP_TASKB_VID_EVEN_BASE, offsets->even_base[cur_buffer]);
+ if (buffer->flags & VIP_INPUTFLAG_VBI)
+ {
+ WRITE_VIP32 (VIP_TASKB_VBI_ODD_BASE, offsets->vbi_odd_base);
+ WRITE_VIP32 (VIP_TASKB_VBI_EVEN_BASE, offsets->vbi_even_base);
+ }
+ }
+
+ /* SET 4:2:0 OFFSETS */
+
+ if (buffer->flags & VIP_INPUTFLAG_PLANAR)
+ {
+ WRITE_VIP32 (VIP_TASKB_U_OFFSET, offsets->odd_uoffset);
+ WRITE_VIP32 (VIP_TASKB_V_OFFSET, offsets->odd_voffset);
+ }
+ }
+ else if (buffer_type == VIP_BUFFER_ANC || buffer_type == VIP_BUFFER_MSG)
+ {
+ WRITE_VIP32(VIP_ANC_MSG1_BASE, buffer->ancillaryData.msg1_base);
+ WRITE_VIP32(VIP_ANC_MSG2_BASE, buffer->ancillaryData.msg2_base);
+ WRITE_VIP32(VIP_ANC_MSG_SIZE, buffer->ancillaryData.msg_size);
+ }
+ else
+ {
+ return CIM_STATUS_INVALIDPARAMS;
+ }
+
+ return CIM_STATUS_OK;
+}
+
+/*---------------------------------------------------------------------------
+ * vip_toggle_vip_video_offsets
+ *
+ * This routine updates the offsets for video capture. It is a simplified
+ * version of vip_configure_capture_buffers that is designed to be called from
+ * interrupt service routines or other buffer flipping applications that
+ * require low latency.
+ *---------------------------------------------------------------------------*/
+
+int vip_toggle_video_offsets (int buffer_type, VIPINPUTBUFFER *buffer)
+{
+ unsigned long cur_buffer = buffer->current_buffer;
+ VIPINPUTBUFFER_ADDR *offsets;
+
+ if (buffer_type == VIP_BUFFER_A)
+ {
+ offsets = &buffer->offsets[VIP_BUFFER_TASK_A];
+
+ /* SET BASE OFFSETS */
+
+ if (buffer->flags & VIP_INPUTFLAG_INVERTPOLARITY)
+ {
+ WRITE_VIP32 (VIP_TASKA_VID_ODD_BASE, offsets->even_base[cur_buffer]);
+ WRITE_VIP32 (VIP_TASKA_VID_EVEN_BASE, offsets->odd_base[cur_buffer]);
+ }
+ else
+ {
+ WRITE_VIP32 (VIP_TASKA_VID_ODD_BASE, offsets->odd_base[cur_buffer]);
+ WRITE_VIP32 (VIP_TASKA_VID_EVEN_BASE, offsets->even_base[cur_buffer]);
+ }
+ }
+ else if (buffer_type == VIP_BUFFER_B)
+ {
+ offsets = &buffer->offsets[VIP_BUFFER_TASK_B];
+
+ /* SET BASE OFFSETS */
+
+ if (buffer->flags & VIP_INPUTFLAG_INVERTPOLARITY)
+ {
+ WRITE_VIP32 (VIP_TASKB_VID_ODD_BASE, offsets->even_base[cur_buffer]);
+ WRITE_VIP32 (VIP_TASKB_VID_EVEN_BASE, offsets->odd_base[cur_buffer]);
+ }
+ else
+ {
+ WRITE_VIP32 (VIP_TASKB_VID_ODD_BASE, offsets->odd_base[cur_buffer]);
+ WRITE_VIP32 (VIP_TASKB_VID_EVEN_BASE, offsets->even_base[cur_buffer]);
+ }
+ }
+ else if (buffer_type == VIP_BUFFER_A_ODD)
+ {
+ offsets = &buffer->offsets[VIP_BUFFER_TASK_A];
+
+ /* SET BASE OFFSETS */
+
+ if (buffer->flags & VIP_INPUTFLAG_INVERTPOLARITY)
+ WRITE_VIP32 (VIP_TASKA_VID_ODD_BASE, offsets->even_base[cur_buffer]);
+ else
+ WRITE_VIP32 (VIP_TASKA_VID_ODD_BASE, offsets->odd_base[cur_buffer]);
+ }
+ else if (buffer_type == VIP_BUFFER_A_EVEN)
+ {
+ offsets = &buffer->offsets[VIP_BUFFER_TASK_A];
+
+ /* SET BASE OFFSETS */
+
+ if (buffer->flags & VIP_INPUTFLAG_INVERTPOLARITY)
+ WRITE_VIP32 (VIP_TASKA_VID_EVEN_BASE, offsets->odd_base[cur_buffer]);
+ else
+ WRITE_VIP32 (VIP_TASKA_VID_EVEN_BASE, offsets->even_base[cur_buffer]);
+ }
+ else if (buffer_type == VIP_BUFFER_B_ODD)
+ {
+ offsets = &buffer->offsets[VIP_BUFFER_TASK_B];
+
+ /* SET BASE OFFSETS */
+
+ if (buffer->flags & VIP_INPUTFLAG_INVERTPOLARITY)
+ WRITE_VIP32 (VIP_TASKB_VID_ODD_BASE, offsets->even_base[cur_buffer]);
+ else
+ WRITE_VIP32 (VIP_TASKB_VID_ODD_BASE, offsets->odd_base[cur_buffer]);
+ }
+ else if (buffer_type == VIP_BUFFER_B_EVEN)
+ {
+ offsets = &buffer->offsets[VIP_BUFFER_TASK_B];
+
+ /* SET BASE OFFSETS */
+
+ if (buffer->flags & VIP_INPUTFLAG_INVERTPOLARITY)
+ WRITE_VIP32 (VIP_TASKB_VID_EVEN_BASE, offsets->odd_base[cur_buffer]);
+ else
+ WRITE_VIP32 (VIP_TASKB_VID_EVEN_BASE, offsets->even_base[cur_buffer]);
+ }
+ else
+ return CIM_STATUS_INVALIDPARAMS;
+
+ return CIM_STATUS_OK;
+}
+
+/*---------------------------------------------------------------------------
+ * vip_set_capture_state
+ *
+ * This routine takes the current control word definition ( stored in locals )
+ * adds in the specified state, and writes the control word.
+ *---------------------------------------------------------------------------*/
+
+int vip_set_capture_state (unsigned long state)
+{
+ unsigned long vip_control1, vip_control3;
+
+ /* UPDATE THE CURRENT CAPTURE MODE */
+
+ vip_control1 = READ_VIP32 (VIP_CONTROL1);
+ vip_control3 = READ_VIP32 (VIP_CONTROL3);
+ vip_control1 &= ~VIP_CONTROL1_RUNMODE_MASK;
+ vip_control1 |= (state << VIP_CONTROL1_RUNMODE_SHIFT);
+
+ WRITE_VIP32 (VIP_CONTROL1, vip_control1);
+
+ if (state >= VIP_STARTCAPTUREATNEXTLINE)
+ {
+ /* WHACK VIP RESET */
+ /* The VIP can get confused when switching between capture settings, such as */
+ /* between linear and planar. We will thus whack VIP reset when enabling */
+ /* capture to ensure a pristine VIP state. */
+
+ WRITE_VIP32 (VIP_CONTROL1, vip_control1 | VIP_CONTROL1_RESET);
+ WRITE_VIP32 (VIP_CONTROL1, vip_control1 & ~VIP_CONTROL1_RESET);
+ WRITE_VIP32 (VIP_CONTROL3, vip_control3 | VIP_CONTROL3_FIFO_RESET);
+ }
+
+ return CIM_STATUS_OK;
+}
+
+/*---------------------------------------------------------------------------
+ * vip_terminate
+ *
+ * This routine stops VIP capture and resets the VIP internal state.
+ *---------------------------------------------------------------------------*/
+
+int vip_terminate (void)
+{
+ unsigned long timeout = 50000;
+
+ /* DISABLE AND CLEAR ALL VIP INTERRUPTS */
+
+ WRITE_VIP32 (VIP_INTERRUPT, VIP_ALL_INTERRUPTS | (VIP_ALL_INTERRUPTS >> 16));
+
+ /* DISABLE VIP CAPTURE */
+ /* We will try to let the VIP FIFO flush before shutting it down. */
+
+ WRITE_VIP32 (VIP_CONTROL1, 0);
+ while (timeout)
+ {
+ timeout--;
+ if (READ_VIP32 (VIP_STATUS) & VIP_STATUS_WRITES_COMPLETE)
+ break;
+ }
+
+ /* RESET THE HARDWARE REGISTERS */
+ /* Note that we enable VIP reset to allow clock gating to lower VIP */
+ /* power consumption. */
+
+ WRITE_VIP32 (VIP_CONTROL1, VIP_CONTROL1_RESET);
+ WRITE_VIP32 (VIP_CONTROL3, VIP_CONTROL3_FIFO_RESET);
+ WRITE_VIP32 (VIP_CONTROL2, 0);
+
+ return CIM_STATUS_OK;
+}
+
+/*---------------------------------------------------------------------------
+ * vip_configure_fifo
+ *
+ * This routine sets the desired threshold or flush for the specified fifo.
+ *---------------------------------------------------------------------------*/
+
+int vip_configure_fifo (unsigned long fifo_type, unsigned long fifo_size)
+{
+ unsigned long vip_control1, vip_control2;
+
+ vip_control1 = READ_VIP32 (VIP_CONTROL1);
+ vip_control2 = READ_VIP32 (VIP_CONTROL2);
+
+ switch (fifo_type)
+ {
+ case VIP_VIDEOTHRESHOLD:
+ vip_control2 &= ~VIP_CONTROL2_VIDTH_MASK;
+ vip_control2 |= (fifo_size << VIP_CONTROL2_VIDTH_SHIFT) & VIP_CONTROL2_VIDTH_MASK;
+ break;
+
+ case VIP_ANCILLARYTHRESHOLD:
+ vip_control2 &= ~VIP_CONTROL2_ANCTH_MASK;
+ vip_control2 |= (fifo_size << VIP_CONTROL2_ANCTH_SHIFT) & VIP_CONTROL2_ANCTH_MASK;
+ break;
+
+ case VIP_VIDEOFLUSH:
+ vip_control1 &= ~VIP_CONTROL1_VID_FF_MASK;
+ vip_control1 |= ((fifo_size >> 2) << VIP_CONTROL1_VID_FF_SHIFT) & VIP_CONTROL1_VID_FF_MASK;
+ break;
+
+ case VIP_ANCILLARYFLUSH:
+ vip_control1 &= ~VIP_CONTROL1_ANC_FF_MASK;
+ vip_control1 |= ((fifo_size >> 2) << VIP_CONTROL1_ANC_FF_SHIFT) & VIP_CONTROL1_ANC_FF_MASK;
+ break;
+
+ default:
+ return CIM_STATUS_INVALIDPARAMS;
+ }
+
+ WRITE_VIP32 (VIP_CONTROL1, vip_control1);
+ WRITE_VIP32 (VIP_CONTROL2, vip_control2);
+
+ return CIM_STATUS_OK;
+}
+
+/*---------------------------------------------------------------------------
+ * vip_set_interrupt_enable
+ *
+ * This routine accepts a mask of interrupts to be enabled/disabled and
+ * an enable flag.
+ *
+ * For each mask match, the interrupt will be enabled or disabled based on
+ * enable
+ *---------------------------------------------------------------------------*/
+
+int vip_set_interrupt_enable (unsigned long mask, int enable)
+{
+ /* CHECK IF ANY VALID INTERRUPTS ARE BEING CHANGED */
+
+ if (mask & VIP_ALL_INTERRUPTS)
+ {
+ unsigned long int_enable = READ_VIP32(VIP_INTERRUPT) & 0xFFFF;
+
+ /* SET OR CLEAR THE MASK BITS */
+ /* Note that the upper 16-bits of the register are 0 after this */
+ /* operation. This prevents us from indadvertently clearing a */
+ /* pending interrupt by enabling/disabling another one. */
+
+ if (enable) int_enable &= ~(mask >> 16);
+ else int_enable |= (mask >> 16);
+
+ WRITE_VIP32 (VIP_INTERRUPT, int_enable);
+ }
+
+ return CIM_STATUS_OK;
+}
+
+/*---------------------------------------------------------------------------
+ * vip_set_vsync_error
+ *
+ * This routine defines a region that is used to determine if the vsync is
+ * within an acceptable range. This definition is accomplished using
+ * a count and a vertical window. The count specifies the exact number
+ * of clocks expected for one field. The window parameters specify the number
+ * of clocks variation allowed before and after the expected vsync. For
+ * example, if vertical_count is 1000, window_before is 5 and window_after
+ * is 12, VSync will be considered valid if it occurs between 995 and 1012
+ * clocks after the last VSync. The total window size (window_before + window_after)
+ * cannot exceed 255.
+ *---------------------------------------------------------------------------*/
+
+int vip_set_vsync_error (unsigned long vertical_count, unsigned long window_before,
+ unsigned long window_after, int enable)
+{
+ unsigned long vip_control2 = READ_VIP32 (VIP_CONTROL2);
+ unsigned long temp;
+
+ if (enable)
+ {
+ /* CREATE THE VERTICAL WINDOW */
+ /* The VIP uses two counters. The first counter defines the minimum clock count */
+ /* before a valid VSync can occur. The second counter starts after the first */
+ /* completes and defines the acceptable region of variation. */
+
+ temp = ((window_before + window_after) << VIP_VSYNC_ERR_WINDOW_SHIFT) & VIP_VSYNC_ERR_WINDOW_MASK;
+ temp |= (vertical_count - window_before) & VIP_VSYNC_ERR_COUNT_MASK;
+
+ vip_control2 |= VIP_CONTROL2_VERTERROR_ENABLE;
+
+ WRITE_VIP32(VIP_VSYNC_ERR_COUNT, temp);
+ }
+ else
+ {
+ vip_control2 &= ~VIP_CONTROL2_VERTERROR_ENABLE;
+ }
+ WRITE_VIP32 (VIP_CONTROL2, vip_control2);
+
+ return CIM_STATUS_OK;
+}
+
+/*---------------------------------------------------------------------------
+ * vip_max_address_enable
+ *
+ * This routine specifies the maximum address to which the the hardware should
+ * write during data storage. If this value is exceeded an error is generated,
+ * (this may be monitored using the appropriate interrupt flags - see
+ * vip_set_interrupt_enable)
+ *---------------------------------------------------------------------------*/
+
+int vip_max_address_enable (unsigned long max_address, int enable)
+{
+ unsigned long vip_control2 = READ_VIP32 (VIP_CONTROL2);
+
+ if (enable)
+ {
+ /* ENABLE THE CONTROL BIT */
+
+ vip_control2 |= VIP_CONTROL2_ADD_ERROR_ENABLE;
+
+ WRITE_VIP32(VIP_MAX_ADDRESS, max_address & VIP_MAXADDR_MASK);
+ }
+ else
+ {
+ /* DISABLE DETECTION */
+
+ vip_control2 &= ~VIP_CONTROL2_ADD_ERROR_ENABLE;
+ }
+ WRITE_VIP32 (VIP_CONTROL2, vip_control2);
+
+ return CIM_STATUS_OK;
+}
+
+/*---------------------------------------------------------------------------
+ * vip_set_loopback_enable
+ *
+ * This routine enables/disables internal loopback functionality. When
+ * loopback is enabled, the VOP outputs are rerouted to the VIP inputs
+ * internal to the chip. No loopback connector is required.
+ *---------------------------------------------------------------------------*/
+
+int vip_set_loopback_enable(int enable)
+{
+ unsigned long vip_control2 = READ_VIP32 (VIP_CONTROL2);
+
+ if (enable) vip_control2 |= VIP_CONTROL2_LOOPBACK_ENABLE;
+ else vip_control2 &= ~VIP_CONTROL2_LOOPBACK_ENABLE;
+
+ WRITE_VIP32 (VIP_CONTROL2, vip_control2);
+
+ return CIM_STATUS_OK;
+}
+
+/*---------------------------------------------------------------------------
+ * vip_configure_genlock
+ *
+ * This routine configures genlock functionality.
+ *---------------------------------------------------------------------------*/
+
+int vip_configure_genlock (VIPGENLOCKBUFFER *buffer)
+{
+ unsigned long vip_control1, vip_control2;
+ unsigned long unlock, genlk_ctl;
+
+ if (!buffer)
+ return CIM_STATUS_INVALIDPARAMS;
+
+ unlock = READ_REG32 (DC3_UNLOCK);
+ genlk_ctl = READ_REG32 (DC3_GENLK_CTL);
+ vip_control1 = READ_VIP32 (VIP_CONTROL1);
+ vip_control2 = READ_VIP32 (VIP_CONTROL2);
+
+ /* UPDATE VIDEO DETECTION */
+ /* These flags are used to indicate the ways in which the VIP signal can */
+ /* be considered 'lost'. */
+
+ vip_control1 &= ~VIP_CONTROL1_VDE_FF_MASK;
+ vip_control2 &= ~(VIP_CONTROL2_FIELD2VG_MASK | VIP_CONTROL2_SYNC2VG_MASK);
+ vip_control1 |= buffer->vip_signal_loss;
+
+ /* UPDATE FIELD AND VSYNC INFORMATION */
+ /* These flags control how and when the even/odd field and Vsync */
+ /* information is communicated to the VG. */
+
+ vip_control2 |= buffer->field_to_vg;
+ vip_control2 |= buffer->vsync_to_vg;
+
+ /* ENABLE OR DISABLE GENLOCK TIMEOUT */
+ /* Enabling genlock timeout allows the VG to revert to its own sync */
+ /* timings when the VIP input is lost. Note that the VIP will not */
+ /* know the signal is lost unless the appropriate error detection */
+ /* flags have been enabled inside vip_initialize. */
+
+ if (buffer->enable_timeout) genlk_ctl |= DC3_GC_GENLOCK_TO_ENABLE;
+ else genlk_ctl &= ~DC3_GC_GENLOCK_TO_ENABLE;
+
+ genlk_ctl &= ~DC3_GC_GENLOCK_SKEW_MASK;
+ genlk_ctl |= buffer->genlock_skew & DC3_GC_GENLOCK_SKEW_MASK;
+
+ WRITE_REG32 (DC3_UNLOCK, DC3_UNLOCK_VALUE);
+ WRITE_REG32 (DC3_GENLK_CTL, genlk_ctl);
+ WRITE_VIP32 (VIP_CONTROL1, vip_control1);
+ WRITE_VIP32 (VIP_CONTROL2, vip_control2);
+ WRITE_REG32 (DC3_UNLOCK, unlock);
+
+ return CIM_STATUS_OK;
+}
+
+/*---------------------------------------------------------------------------
+ * vip_set_genlock_enable
+ *
+ * This routine enables/disables genlock inside the VG.
+ *---------------------------------------------------------------------------*/
+
+int vip_set_genlock_enable (int enable)
+{
+ unsigned long unlock, temp;
+
+ unlock = READ_REG32 (DC3_UNLOCK);
+ temp = READ_REG32 (DC3_GENLK_CTL);
+
+ if (enable) temp |= DC3_GC_GENLOCK_ENABLE;
+ else temp &= ~DC3_GC_GENLOCK_ENABLE;
+
+ WRITE_REG32 (DC3_UNLOCK, DC3_UNLOCK_VALUE);
+ WRITE_REG32 (DC3_GENLK_CTL, temp);
+ WRITE_REG32 (DC3_UNLOCK, unlock);
+
+ return CIM_STATUS_OK;
+}
+
+/*---------------------------------------------------------------------------
+ * vip_set_power_characteristics
+ *
+ * This routine takes a VIPPOWERBUFFER structure, and selectively sets the
+ * GeodeLink power and/or Vip clock power states.
+ *---------------------------------------------------------------------------*/
+
+int vip_set_power_characteristics (VIPPOWERBUFFER *buffer)
+{
+ Q_WORD q_word;
+
+ if (!buffer)
+ return CIM_STATUS_INVALIDPARAMS;
+
+ q_word.low = q_word.high = 0;
+
+ /* ENABLE GEODELINK CLOCK GATING */
+
+ if (buffer->glink_clock_mode)
+ q_word.low |= VIP_MSR_POWER_GLINK;
+
+ /* ENABLE VIP CLOCK GATING */
+
+ if (buffer->vip_clock_mode)
+ q_word.low |= VIP_MSR_POWER_CLOCK;
+
+ /* WRITE THE NEW VALUE */
+
+ msr_write64 (MSR_DEVICE_GEODELX_VIP, MSR_GEODELINK_PM, &q_word);
+
+ return CIM_STATUS_OK;
+}
+
+/*---------------------------------------------------------------------------
+ * vip_set_priority_characteristics
+ *
+ * This routine programs the VIP GeodeLink priority characteristics
+ *---------------------------------------------------------------------------*/
+
+int vip_set_priority_characteristics (VIPPRIORITYBUFFER *buffer)
+{
+ Q_WORD q_word;
+
+ if (!buffer)
+ return CIM_STATUS_INVALIDPARAMS;
+
+ q_word.low = q_word.high = 0;
+
+ q_word.low |= (buffer->secondary << VIP_MSR_MCR_SECOND_PRIORITY_SHIFT) & VIP_MSR_MCR_SECOND_PRIORITY_MASK;
+ q_word.low |= (buffer->primary << VIP_MSR_MCR_PRIMARY_PRIORITY_SHIFT) & VIP_MSR_MCR_PRIMARY_PRIORITY_MASK;
+ q_word.low |= (buffer->pid << VIP_MSR_MCR_PID_SHIFT) & VIP_MSR_MCR_PID_MASK;
+
+ msr_write64 (MSR_DEVICE_GEODELX_VIP, MSR_GEODELINK_CONFIG, &q_word);
+
+ return CIM_STATUS_OK;
+}
+
+/*---------------------------------------------------------------------------
+ * vip_set_debug_characteristics
+ *
+ * This routine configures the debug data that is exposed over the diag bus.
+ *---------------------------------------------------------------------------*/
+
+int vip_set_debug_characteristics (VIPDEBUGBUFFER *buffer)
+{
+ Q_WORD q_word;
+
+ if (!buffer)
+ return CIM_STATUS_INVALIDPARAMS;
+
+ q_word.low = q_word.high = 0;
+
+ q_word.high |= (buffer->bist << VIP_MSR_DIAG_BIST_SHIFT) & VIP_MSR_DIAG_BIST_WMASK;
+ q_word.low |= (buffer->enable_upper ? VIP_MSR_DIAG_MSB_ENABLE : 0x00000000);
+ q_word.low |= (buffer->select_upper << VIP_MSR_DIAG_SEL_UPPER_SHIFT) & VIP_MSR_DIAG_SEL_UPPER_MASK;
+ q_word.low |= (buffer->enable_lower ? VIP_MSR_DIAG_LSB_ENABLE : 0x00000000 );
+ q_word.low |= (buffer->select_lower << VIP_MSR_DIAG_SEL_LOWER_SHIFT) & VIP_MSR_DIAG_SEL_LOWER_MASK;
+
+ msr_write64 (MSR_DEVICE_GEODELX_VIP, MSR_GEODELINK_DIAG, &q_word);
+
+ return CIM_STATUS_OK;
+}
+
+/*---------------------------------------------------------------------------
+ * vip_configure_pages
+ *
+ * This routine sets the number of pages, and their offset from each other.
+ *---------------------------------------------------------------------------*/
+
+int vip_configure_pages (int page_count, unsigned long page_offset)
+{
+ unsigned long vip_control2 = READ_VIP32 (VIP_CONTROL2);
+
+ /* SET THE NEW PAGE COUNT */
+
+ vip_control2 &= ~VIP_CONTROL2_PAGECNT_MASK;
+ vip_control2 |= (page_count << VIP_CONTROL2_PAGECNT_SHIFT) & VIP_CONTROL2_PAGECNT_MASK;
+
+ /* WRITE THE PAGE OFFSET */
+
+ WRITE_VIP32 (VIP_CONTROL2, vip_control2);
+ WRITE_VIP32 (VIP_PAGE_OFFSET, page_offset);
+
+ return CIM_STATUS_OK;
+}
+
+/*---------------------------------------------------------------------------
+ * vip_set_interrupt_line
+ *
+ * This routine sets the line at which a line interrupt should be generated.
+ *---------------------------------------------------------------------------*/
+
+int vip_set_interrupt_line (int line)
+{
+ WRITE_VIP32 (VIP_CURRENT_TARGET, (line << VIP_CTARGET_TLINE_SHIFT) & VIP_CTARGET_TLINE_MASK);
+
+ return CIM_STATUS_OK;
+}
+
+/*---------------------------------------------------------------------------
+ * vip_reset
+ *
+ * This routine does a one-shot enable of the VIP hardware. It is useful
+ * for handling unrecoverable VIP errors.
+ *---------------------------------------------------------------------------*/
+
+int vip_reset (void)
+{
+ unsigned long vip_control1, vip_control3;
+
+ /* INVERT THE PAUSE BIT */
+
+ vip_control1 = READ_VIP32 (VIP_CONTROL1);
+ vip_control3 = READ_VIP32 (VIP_CONTROL3);
+
+ WRITE_VIP32 (VIP_CONTROL1, vip_control1 | VIP_CONTROL1_RESET);
+ WRITE_VIP32 (VIP_CONTROL1, vip_control1 & ~VIP_CONTROL1_RESET);
+ WRITE_VIP32 (VIP_CONTROL3, vip_control3 | VIP_CONTROL3_FIFO_RESET);
+
+ return CIM_STATUS_OK;
+}
+
+/*---------------------------------------------------------------------------
+ * vip_set_subwindow_enable
+ *
+ * This routine turns on SubWindow capture, that is a portion of the incoming
+ * signal is captured rather than the entire frame. The window always has
+ * the same width as the frame, only the vertical component can be
+ * modified.
+ *---------------------------------------------------------------------------*/
+
+int vip_set_subwindow_enable (VIPSUBWINDOWBUFFER *buffer)
+{
+ unsigned long vip_control2;
+
+ if (!buffer)
+ return CIM_STATUS_INVALIDPARAMS;
+
+ vip_control2 = READ_VIP32 (VIP_CONTROL2);
+ if (buffer->enable)
+ {
+ /* WRITE THE WINDOW VALUE */
+
+ WRITE_VIP32(VIP_VERTICAL_START_STOP,
+ ((buffer->stop << VIP_VSTART_VERTEND_SHIFT) & VIP_VSTART_VERTEND_MASK) |
+ ((buffer->start << VIP_VSTART_VERTSTART_SHIFT) & VIP_VSTART_VERTSTART_MASK));
+
+ /* ENABLE IN THE CONTROL REGISTER */
+
+ vip_control2 |= VIP_CONTROL2_SWC_ENABLE;
+ }
+ else
+ {
+ /* DISABLE SUBWINDOW CAPTURE IN THE CONTROL REGISTER */
+
+ vip_control2 &= ~VIP_CONTROL2_SWC_ENABLE;
+ }
+ WRITE_VIP32 (VIP_CONTROL2, vip_control2);
+
+ return CIM_STATUS_OK;
+}
+
+/*---------------------------------------------------------------------------
+ * vip_reset_interrupt_state
+ *
+ * This routine resets the state of one or more interrupts.
+ *---------------------------------------------------------------------------*/
+
+int vip_reset_interrupt_state(unsigned long interrupt_mask)
+{
+ unsigned long temp;
+
+ temp = READ_VIP32(VIP_INTERRUPT);
+ WRITE_VIP32 (VIP_INTERRUPT, temp | (interrupt_mask & VIP_ALL_INTERRUPTS));
+
+ return CIM_STATUS_OK;
+}
+
+/*---------------------------------------------------------------------------
+ * vip_save_state
+ *
+ * This routine saves the necessary register contents in order to restore
+ * at a later point to the same state.
+ *
+ * NOTE: Capture state is forced to OFF in this routine
+ *---------------------------------------------------------------------------*/
+
+int vip_save_state(VIPSTATEBUFFER *save_buffer)
+{
+ if (!save_buffer)
+ return CIM_STATUS_INVALIDPARAMS;
+
+ /* FORCE CAPTURE TO BE DISABLED */
+
+ vip_set_capture_state (VIP_STOPCAPTURE);
+
+ /* READ AND SAVE THE REGISTER CONTENTS */
+
+ save_buffer->control1 = READ_VIP32(VIP_CONTROL1);
+ save_buffer->control2 = READ_VIP32(VIP_CONTROL2);
+ save_buffer->vip_int = READ_VIP32(VIP_INTERRUPT);
+ save_buffer->current_target = READ_VIP32(VIP_CURRENT_TARGET);
+ save_buffer->max_address = READ_VIP32(VIP_MAX_ADDRESS);
+ save_buffer->taska_evenbase = READ_VIP32(VIP_TASKA_VID_EVEN_BASE);
+ save_buffer->taska_oddbase = READ_VIP32(VIP_TASKA_VID_ODD_BASE);
+ save_buffer->taska_vbi_evenbase = READ_VIP32(VIP_TASKA_VBI_EVEN_BASE);
+ save_buffer->taska_vbi_oddbase = READ_VIP32(VIP_TASKA_VBI_ODD_BASE);
+ save_buffer->taska_data_pitch = READ_VIP32(VIP_TASKA_VID_PITCH);
+ save_buffer->control3 = READ_VIP32(VIP_CONTROL3);
+ save_buffer->taska_v_oddoffset = READ_VIP32(VIP_TASKA_U_OFFSET);
+ save_buffer->taska_u_oddoffset = READ_VIP32(VIP_TASKA_V_OFFSET);
+ save_buffer->taskb_evenbase = READ_VIP32(VIP_TASKB_VID_EVEN_BASE);
+ save_buffer->taskb_oddbase = READ_VIP32(VIP_TASKB_VID_ODD_BASE);
+ save_buffer->taskb_vbi_evenbase = READ_VIP32(VIP_TASKB_VBI_EVEN_BASE);
+ save_buffer->taskb_vbi_oddbase = READ_VIP32(VIP_TASKB_VBI_ODD_BASE);
+ save_buffer->taskb_pitch = READ_VIP32(VIP_TASKB_VID_PITCH);
+ save_buffer->taskb_voffset = READ_VIP32(VIP_TASKB_U_OFFSET);
+ save_buffer->taskb_uoffset = READ_VIP32(VIP_TASKB_V_OFFSET);
+ save_buffer->msg1_base = READ_VIP32(VIP_ANC_MSG1_BASE);
+ save_buffer->msg2_base = READ_VIP32(VIP_ANC_MSG2_BASE);
+ save_buffer->msg_size = READ_VIP32(VIP_ANC_MSG_SIZE);
+ save_buffer->page_offset = READ_VIP32(VIP_PAGE_OFFSET);
+ save_buffer->vert_start_stop = READ_VIP32(VIP_VERTICAL_START_STOP);
+ save_buffer->vsync_err_count = READ_VIP32(VIP_VSYNC_ERR_COUNT);
+ save_buffer->taska_u_evenoffset = READ_VIP32(VIP_TASKA_U_EVEN_OFFSET);
+ save_buffer->taska_v_evenoffset = READ_VIP32(VIP_TASKA_V_EVEN_OFFSET);
+
+ /* READ ALL VIP MSRS */
+
+ msr_read64 (MSR_DEVICE_GEODELX_VIP, MSR_GEODELINK_CONFIG, &(save_buffer->msr_config));
+ msr_read64 (MSR_DEVICE_GEODELX_VIP, MSR_GEODELINK_SMI, &(save_buffer->msr_smi));
+ msr_read64 (MSR_DEVICE_GEODELX_VIP, MSR_GEODELINK_PM, &(save_buffer->msr_pm));
+ msr_read64 (MSR_DEVICE_GEODELX_VIP, MSR_GEODELINK_DIAG, &(save_buffer->msr_diag));
+
+ return CIM_STATUS_OK;
+}
+
+/*---------------------------------------------------------------------------
+ * vip_restore_state
+ *
+ * This routine restores the state of the vip registers - which were
+ * previously saved using vip_save_state.
+ *---------------------------------------------------------------------------*/
+
+int vip_restore_state (VIPSTATEBUFFER *restore_buffer)
+{
+ if (!restore_buffer)
+ return CIM_STATUS_OK;
+
+ /* RESTORE THE REGISTERS */
+
+ WRITE_VIP32(VIP_CURRENT_TARGET, restore_buffer->current_target);
+ WRITE_VIP32(VIP_MAX_ADDRESS, restore_buffer->max_address);
+ WRITE_VIP32(VIP_TASKA_VID_EVEN_BASE, restore_buffer->taska_evenbase);
+ WRITE_VIP32(VIP_TASKA_VID_ODD_BASE, restore_buffer->taska_oddbase);
+ WRITE_VIP32(VIP_TASKA_VBI_EVEN_BASE, restore_buffer->taska_vbi_evenbase);
+ WRITE_VIP32(VIP_TASKA_VBI_ODD_BASE, restore_buffer->taska_vbi_oddbase);
+ WRITE_VIP32(VIP_TASKA_VID_PITCH, restore_buffer->taska_data_pitch);
+ WRITE_VIP32(VIP_CONTROL3, restore_buffer->control3);
+ WRITE_VIP32(VIP_TASKA_U_OFFSET, restore_buffer->taska_v_oddoffset);
+ WRITE_VIP32(VIP_TASKA_V_OFFSET, restore_buffer->taska_u_oddoffset);
+ WRITE_VIP32(VIP_TASKB_VID_EVEN_BASE, restore_buffer->taskb_evenbase);
+ WRITE_VIP32(VIP_TASKB_VID_ODD_BASE, restore_buffer->taskb_oddbase);
+ WRITE_VIP32(VIP_TASKB_VBI_EVEN_BASE, restore_buffer->taskb_vbi_evenbase);
+ WRITE_VIP32(VIP_TASKB_VBI_ODD_BASE, restore_buffer->taskb_vbi_oddbase);
+ WRITE_VIP32(VIP_TASKB_VID_PITCH, restore_buffer->taskb_pitch);
+ WRITE_VIP32(VIP_TASKB_U_OFFSET, restore_buffer->taskb_voffset);
+ WRITE_VIP32(VIP_TASKB_V_OFFSET, restore_buffer->taskb_uoffset);
+ WRITE_VIP32(VIP_ANC_MSG1_BASE, restore_buffer->msg1_base);
+ WRITE_VIP32(VIP_ANC_MSG2_BASE, restore_buffer->msg2_base);
+ WRITE_VIP32(VIP_ANC_MSG_SIZE, restore_buffer->msg_size);
+ WRITE_VIP32(VIP_PAGE_OFFSET, restore_buffer->page_offset);
+ WRITE_VIP32(VIP_VERTICAL_START_STOP, restore_buffer->vert_start_stop);
+ WRITE_VIP32(VIP_VSYNC_ERR_COUNT, restore_buffer->vsync_err_count);
+ WRITE_VIP32(VIP_TASKA_U_EVEN_OFFSET, restore_buffer->taska_u_evenoffset);
+ WRITE_VIP32(VIP_TASKA_V_EVEN_OFFSET, restore_buffer->taska_v_evenoffset);
+
+ /* RESTORE THE VIP MSRS */
+
+ msr_write64 (MSR_DEVICE_GEODELX_VIP, MSR_GEODELINK_CONFIG, &(restore_buffer->msr_config));
+ msr_write64 (MSR_DEVICE_GEODELX_VIP, MSR_GEODELINK_SMI, &(restore_buffer->msr_smi));
+ msr_write64 (MSR_DEVICE_GEODELX_VIP, MSR_GEODELINK_PM, &(restore_buffer->msr_pm));
+ msr_write64 (MSR_DEVICE_GEODELX_VIP, MSR_GEODELINK_DIAG, &(restore_buffer->msr_diag));
+
+ /* RESTORE THE CONTROL WORDS LAST */
+
+ WRITE_VIP32(VIP_CONTROL1, restore_buffer->control1);
+ WRITE_VIP32(VIP_CONTROL2, restore_buffer->control2);
+ WRITE_VIP32(VIP_CONTROL3, restore_buffer->control3);
+
+ return CIM_STATUS_OK;
+}
+
+/*---------------------------------------------------------------------------
+ * vip_get_interrupt_state
+ *
+ * This routine returns the current interrupt state of the system. The
+ * rv can be tested with the following flags to determine if the appropriate
+ * event has occured.
+ *---------------------------------------------------------------------------*/
+
+unsigned long vip_get_interrupt_state(void)
+{
+ unsigned long interrupt_mask = READ_VIP32(VIP_INTERRUPT);
+
+ return (~(interrupt_mask << 16) & interrupt_mask & VIP_ALL_INTERRUPTS);
+}
+
+/*---------------------------------------------------------------------------
+ * vip_test_genlock_active
+ *
+ * This routine reads the live status of the genlock connection between the VIP
+ * and VG blocks.
+ *---------------------------------------------------------------------------*/
+
+int vip_test_genlock_active (void)
+{
+ if (READ_REG32 (DC3_GENLK_CTL) & DC3_GC_GENLK_ACTIVE)
+ return 1;
+
+ return 0;
+}
+
+/*---------------------------------------------------------------------------
+ * vip_test_signal_status
+ *
+ * This routine reads the live signal status coming into the VIP block.
+ *---------------------------------------------------------------------------*/
+
+int vip_test_signal_status (void)
+{
+ if (READ_REG32 (DC3_GENLK_CTL) & DC3_GC_VIP_VID_OK)
+ return 1;
+
+ return 0;
+}
+
+/*---------------------------------------------------------------------------
+ * vip_get_current_field
+ *
+ * This routine returns the current field being received.
+ *---------------------------------------------------------------------------*/
+
+unsigned long vip_get_current_field (void)
+{
+ if (READ_VIP32(VIP_STATUS) & VIP_STATUS_FIELD)
+ return VIP_EVEN_FIELD;
+
+ return VIP_ODD_FIELD;
+}
+
+/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ * CIMARRON VIP READ ROUTINES
+ * These routines are included for use in diagnostics or when debugging. They
+ * can be optionally excluded from a project.
+ *+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
+
+#if CIMARRON_INCLUDE_VIP_READ_ROUTINES
+
+/*---------------------------------------------------------------------------
+ * vip_get_current_mode
+ *
+ * This routine reads the current VIP operating mode.
+ *---------------------------------------------------------------------------*/
+
+int vip_get_current_mode (VIPSETMODEBUFFER *buffer)
+{
+ unsigned long vip_control1, vip_control2, vip_control3;
+
+ if (!buffer)
+ return CIM_STATUS_INVALIDPARAMS;
+
+ vip_control1 = READ_VIP32 (VIP_CONTROL1);
+ vip_control2 = READ_VIP32 (VIP_CONTROL2);
+ vip_control3 = READ_VIP32 (VIP_CONTROL3);
+
+ /* READ CURRENT OPERATING MODE AND ENABLES */
+
+ buffer->stream_enables = vip_control1 & VIP_ENABLE_ALL;
+ buffer->operating_mode = vip_control1 & VIP_CONTROL1_MODE_MASK;
+
+ /* READ CURRENT PLANAR CAPTURE SETTINGS */
+
+ buffer->flags = 0;
+ buffer->planar_capture = 0;
+ if (vip_control1 & VIP_CONTROL1_PLANAR)
+ {
+ buffer->flags |= VIP_MODEFLAG_PLANARCAPTURE;
+ if (vip_control1 & VIP_CONTROL1_DISABLE_DECIMATION)
+ {
+ if (vip_control3 & VIP_CONTROL3_DECIMATE_EVEN)
+ buffer->planar_capture = VIP_420CAPTURE_ALTERNATINGFIELDS;
+ else
+ buffer->planar_capture = VIP_420CAPTURE_EVERYLINE;
+ }
+ else
+ buffer->planar_capture = VIP_420CAPTURE_ALTERNATINGLINES;
+ }
+
+ /* READ MISCELLANEOUS FLAGS */
+
+ if (vip_control1 & VIP_CONTROL1_NON_INTERLACED)
+ buffer->flags |= VIP_MODEFLAG_PROGRESSIVE;
+ if (vip_control3 & VIP_CONTROL3_BASE_UPDATE)
+ buffer->flags |= VIP_MODEFLAG_TOGGLEEACHFIELD;
+ if (vip_control2 & VIP_CONTROL2_INVERT_POLARITY)
+ buffer->flags |= VIP_MODEFLAG_INVERTPOLARITY;
+ if (vip_control1 & VIP_CONTROL1_MSG_STRM_CTRL)
+ buffer->flags |= VIP_MODEFLAG_FLIPMESSAGEWHENFULL;
+ if (vip_control2 & VIP_CONTROL2_REPEAT_ENABLE)
+ buffer->flags |= VIP_MODEFLAG_ENABLEREPEATFLAG;
+ if (vip_control3 & VIP_CONTROL3_TASK_POLARITY)
+ buffer->flags |= VIP_MODEFLAG_INVERTTASKPOLARITY;
+ if (vip_control1 & VIP_CONTROL1_DISABLE_ZERO_DETECT)
+ buffer->flags |= VIP_MODEFLAG_DISABLEZERODETECT;
+ if (vip_control2 & VIP_CONTROL2_ANC10)
+ buffer->flags |= VIP_MODEFLAG_10BITANCILLARY;
+
+ /* READ THE CURRENT VIP 601 SETTINGS */
+
+ vip_get_601_configuration (&buffer->vip601_settings);
+
+ return CIM_STATUS_OK;
+}
+
+/*---------------------------------------------------------------------------
+ * vip_get_601_configuration
+ *
+ * This routine returns the current 601 configuration information.
+ *---------------------------------------------------------------------------*/
+
+int vip_get_601_configuration (VIP_601PARAMS *buffer)
+{
+ unsigned long vip_control3, vip_control1;
+
+ if (!buffer)
+ return CIM_STATUS_INVALIDPARAMS;
+
+ vip_control1 = READ_VIP32 (VIP_CONTROL3);
+ vip_control3 = READ_VIP32 (VIP_CONTROL3);
+
+ buffer->flags = 0;
+ if (vip_control3 & VIP_CONTROL3_VSYNC_POLARITY) buffer->flags |= VIP_MODEFLAG_VSYNCACTIVEHIGH;
+ if (vip_control3 & VIP_CONTROL3_HSYNC_POLARITY) buffer->flags |= VIP_MODEFLAG_HSYNCACTIVEHIGH;
+
+ buffer->horz_start = READ_VIP32 (VIP_601_HORZ_START);
+ buffer->vbi_start = READ_VIP32 (VIP_601_VBI_START);
+ buffer->vbi_height = READ_VIP32 (VIP_601_VBI_END) - buffer->vbi_start + 1;
+ buffer->vert_start_even = READ_VIP32 (VIP_601_EVEN_START_STOP) & 0xFFFF;
+ buffer->even_height = (READ_VIP32 (VIP_601_EVEN_START_STOP) >> 16) - buffer->vert_start_even + 1;
+ buffer->vert_start_odd = READ_VIP32 (VIP_601_ODD_START_STOP) & 0xFFFF;
+ buffer->odd_height = (READ_VIP32 (VIP_601_ODD_START_STOP) >> 16) - buffer->vert_start_odd + 1;
+ buffer->odd_detect_start = READ_VIP32 (VIP_ODD_FIELD_DETECT) & 0xFFFF;
+ buffer->odd_detect_end = READ_VIP32 (VIP_ODD_FIELD_DETECT) >> 16;
+
+ /* SPECIAL CASE FOR HORIZONTAL DATA */
+ /* 601 horizontal parameters are based on the number of clocks and not the */
+ /* number of pixels. */
+
+ if ((vip_control1 & VIP_CONTROL1_MODE_MASK) == VIP_MODE_16BIT601)
+ buffer->width = (READ_VIP32 (VIP_601_HORZ_END) - buffer->horz_start - 3) >> 1;
+ else
+ buffer->width = (READ_VIP32 (VIP_601_HORZ_END) - buffer->horz_start - 3);
+
+ return CIM_STATUS_OK;
+}
+
+/*---------------------------------------------------------------------------
+ * vip_get_buffer_configuration
+ *
+ * This routine reads the current buffer configuration for Task A, Task B,
+ * ancillary or message data. The current_buffer member indicates which
+ * array index should hold the new values for Task A or Task B data.
+ *---------------------------------------------------------------------------*/
+
+int vip_get_buffer_configuration (int buffer_type, VIPINPUTBUFFER *buffer)
+{
+ unsigned long cur_buffer = buffer->current_buffer;
+ VIPINPUTBUFFER_ADDR *offsets;
+
+ if (!buffer)
+ return CIM_STATUS_INVALIDPARAMS;
+
+ if (buffer_type == VIP_BUFFER_A)
+ {
+ offsets = &buffer->offsets[VIP_BUFFER_TASK_A];
+
+ /* READ VIDEO PITCH */
+
+ offsets->y_pitch = READ_VIP32 (VIP_TASKA_VID_PITCH) & 0xFFFF;
+ offsets->uv_pitch = READ_VIP32 (VIP_TASKA_VID_PITCH) >> 16;
+
+ /* READ BASE OFFSETS */
+
+ if (buffer->flags & VIP_INPUTFLAG_INVERTPOLARITY)
+ {
+ offsets->even_base[cur_buffer] = READ_VIP32 (VIP_TASKA_VID_ODD_BASE);
+ offsets->odd_base[cur_buffer] = READ_VIP32 (VIP_TASKA_VID_EVEN_BASE);
+
+ if (buffer->flags & VIP_INPUTFLAG_VBI)
+ {
+ offsets->vbi_even_base = READ_VIP32 (VIP_TASKA_VBI_ODD_BASE);
+ offsets->vbi_odd_base = READ_VIP32 (VIP_TASKA_VBI_EVEN_BASE);
+ }
+ }
+ else
+ {
+ offsets->even_base[cur_buffer] = READ_VIP32 (VIP_TASKA_VID_EVEN_BASE);
+ offsets->odd_base[cur_buffer] = READ_VIP32 (VIP_TASKA_VID_ODD_BASE);
+
+ if (buffer->flags & VIP_INPUTFLAG_VBI)
+ {
+ offsets->vbi_even_base = READ_VIP32 (VIP_TASKA_VBI_EVEN_BASE);
+ offsets->vbi_odd_base = READ_VIP32 (VIP_TASKA_VBI_ODD_BASE);
+ }
+ }
+
+ /* READ 4:2:0 OFFSETS */
+
+ if (buffer->flags & VIP_INPUTFLAG_PLANAR)
+ {
+ offsets->odd_uoffset = READ_VIP32 (VIP_TASKA_U_OFFSET);
+ offsets->odd_voffset = READ_VIP32 (VIP_TASKA_V_OFFSET);
+ offsets->even_uoffset = READ_VIP32 (VIP_TASKA_U_EVEN_OFFSET);
+ offsets->even_voffset = READ_VIP32 (VIP_TASKA_V_EVEN_OFFSET);
+ }
+ }
+ else if (buffer_type == VIP_BUFFER_B)
+ {
+ offsets = &buffer->offsets[VIP_BUFFER_TASK_B];
+
+ /* READ VIDEO PITCH */
+
+ offsets->y_pitch = READ_VIP32 (VIP_TASKB_VID_PITCH) & 0xFFFF;
+ offsets->uv_pitch = READ_VIP32 (VIP_TASKB_VID_PITCH) >> 16;
+
+ /* READ BASE OFFSETS */
+
+ if (buffer->flags & VIP_INPUTFLAG_INVERTPOLARITY)
+ {
+ offsets->even_base[cur_buffer] = READ_VIP32 (VIP_TASKB_VID_ODD_BASE);
+ offsets->odd_base[cur_buffer] = READ_VIP32 (VIP_TASKB_VID_EVEN_BASE);
+
+ if (buffer->flags & VIP_INPUTFLAG_VBI)
+ {
+ offsets->vbi_even_base = READ_VIP32 (VIP_TASKB_VBI_ODD_BASE);
+ offsets->vbi_odd_base = READ_VIP32 (VIP_TASKB_VBI_EVEN_BASE);
+ }
+ }
+ else
+ {
+ offsets->even_base[cur_buffer] = READ_VIP32 (VIP_TASKB_VID_EVEN_BASE);
+ offsets->odd_base[cur_buffer] = READ_VIP32 (VIP_TASKB_VID_ODD_BASE);
+
+ if (buffer->flags & VIP_INPUTFLAG_VBI)
+ {
+ offsets->vbi_even_base = READ_VIP32 (VIP_TASKB_VBI_EVEN_BASE);
+ offsets->vbi_odd_base = READ_VIP32 (VIP_TASKB_VBI_ODD_BASE);
+ }
+ }
+
+ /* READ 4:2:0 OFFSETS */
+
+ if (buffer->flags & VIP_INPUTFLAG_PLANAR)
+ {
+ offsets->odd_uoffset = READ_VIP32 (VIP_TASKB_U_OFFSET);
+ offsets->odd_voffset = READ_VIP32 (VIP_TASKB_V_OFFSET);
+ }
+ }
+ else if (buffer_type == VIP_BUFFER_ANC || buffer_type == VIP_BUFFER_MSG)
+ {
+ buffer->ancillaryData.msg1_base = READ_VIP32(VIP_ANC_MSG1_BASE);
+ buffer->ancillaryData.msg2_base = READ_VIP32(VIP_ANC_MSG2_BASE);
+ buffer->ancillaryData.msg_size = READ_VIP32(VIP_ANC_MSG_SIZE);
+ }
+ else
+ {
+ return CIM_STATUS_INVALIDPARAMS;
+ }
+
+ return CIM_STATUS_OK;
+}
+
+/*---------------------------------------------------------------------------
+ * vip_get_genlock_configuration
+ *
+ * This routine reads the current genlock configuration.
+ *---------------------------------------------------------------------------*/
+
+int vip_get_genlock_configuration (VIPGENLOCKBUFFER *buffer)
+{
+ unsigned long vip_control1, vip_control2;
+ unsigned long genlk_ctl;
+
+ if (!buffer)
+ return CIM_STATUS_INVALIDPARAMS;
+
+ genlk_ctl = READ_REG32 (DC3_GENLK_CTL);
+ vip_control1 = READ_VIP32 (VIP_CONTROL1);
+ vip_control2 = READ_VIP32 (VIP_CONTROL2);
+
+ /* READ ERROR DETECTION, CURRENT FIELD AND CURRENT VSYNC */
+ /* These flags are used to indicate the ways in which the VIP signal can */
+ /* be considered 'lost'. */
+
+ buffer->vip_signal_loss = vip_control1 & VIP_CONTROL1_VDE_FF_MASK;
+ buffer->field_to_vg = vip_control2 & VIP_CONTROL2_FIELD2VG_MASK;
+ buffer->vsync_to_vg = vip_control2 & VIP_CONTROL2_SYNC2VG_MASK;
+
+ /* GENLOCK TIMEOUT ENABLE */
+
+ buffer->enable_timeout = 0;
+ if (genlk_ctl & DC3_GC_GENLOCK_TO_ENABLE)
+ buffer->enable_timeout = 1;
+
+ /* GENLOCK SKEW */
+
+ buffer->genlock_skew = genlk_ctl & DC3_GC_GENLOCK_SKEW_MASK;
+
+ return CIM_STATUS_OK;
+}
+
+/*---------------------------------------------------------------------------
+ * vip_get_genlock_enable
+ *
+ * This routine returns the current enable status of genlock in the VG.
+ *---------------------------------------------------------------------------*/
+
+int vip_get_genlock_enable (void)
+{
+ if (READ_REG32 (DC3_GENLK_CTL) & DC3_GC_GENLOCK_ENABLE)
+ return 1;
+
+ return 0;
+}
+
+/*---------------------------------------------------------------------------
+ * vip_is_buffer_update_latched
+ *
+ * This routine indicates whether changes to the VIP offsets have been latched by
+ * the hardware.
+ *---------------------------------------------------------------------------*/
+
+int vip_is_buffer_update_latched (void)
+{
+ return (!(READ_VIP32(VIP_STATUS) & VIP_STATUS_BASEREG_NOTUPDT));
+}
+
+/*---------------------------------------------------------------------------
+ * vip_get_capture_state
+ *
+ * This routine reads the current capture status of the VIP hardware.
+ *---------------------------------------------------------------------------*/
+
+unsigned long vip_get_capture_state (void)
+{
+ return ((READ_VIP32(VIP_CONTROL1) & VIP_CONTROL1_RUNMODE_MASK) >> VIP_CONTROL1_RUNMODE_SHIFT);
+}
+
+/*---------------------------------------------------------------------------
+ * vip_get_current_line
+ *
+ * This routine returns the current line that is being processed.
+ *---------------------------------------------------------------------------*/
+
+unsigned long vip_get_current_line (void)
+{
+ return (READ_VIP32(VIP_CURRENT_TARGET) & VIP_CTARGET_CLINE_MASK);
+}
+
+/*---------------------------------------------------------------------------
+ * vip_read_fifo
+ *
+ * This routine reads from the specified fifo address. As the fifo access
+ * enable should be disabled when running in normal vip mode, this routine
+ * enables and disables access around the read.
+ * DIAGNOSTIC USE ONLY
+ *---------------------------------------------------------------------------*/
+
+unsigned long vip_read_fifo(unsigned long dwFifoAddress)
+{
+ unsigned long fifo_data;
+
+ /* ENABLE FIFO ACCESS */
+
+ vip_enable_fifo_access (1);
+
+ /* NOW READ THE DATA */
+
+ WRITE_VIP32(VIP_FIFO_ADDRESS, dwFifoAddress);
+ fifo_data = READ_VIP32(VIP_FIFO_DATA);
+
+ /* DISABLE FIFO ACCESS */
+
+ vip_enable_fifo_access (0);
+
+ return fifo_data;
+}
+
+/*---------------------------------------------------------------------------
+ * vip_write_fifo
+ *
+ * SYNOPSIS:
+ * This routine writes to the specified fifo address. As the fifo access
+ * enable should be disabled when running in normal vip mode, this routine
+ * enables and disables access around the write.
+ * DIAGNOSTIC USE ONLY
+ *---------------------------------------------------------------------------*/
+
+int vip_write_fifo (unsigned long dwFifoAddress, unsigned long dwFifoData)
+{
+ /* ENABLE FIFO ACCESS */
+
+ vip_enable_fifo_access(1);
+
+ /* WRITE THE FIFO DATA */
+
+ WRITE_VIP32(VIP_FIFO_ADDRESS, dwFifoAddress);
+ WRITE_VIP32(VIP_FIFO_DATA, dwFifoData);
+
+ /* DISABLE FIFO ACCESS */
+
+ vip_enable_fifo_access(0);
+
+ return CIM_STATUS_OK;
+}
+
+/*---------------------------------------------------------------------------
+ * vip_enable_fifo_access
+ *
+ * This routine enables/disables access to the vip fifo.
+ * DIAGNOSTIC USE ONLY
+ *---------------------------------------------------------------------------*/
+
+int vip_enable_fifo_access (int enable)
+{
+ unsigned long cw2;
+
+ cw2 = READ_VIP32(VIP_CONTROL2);
+
+ if (enable) cw2 |= VIP_CONTROL2_FIFO_ACCESS;
+ else cw2 &= ~VIP_CONTROL2_FIFO_ACCESS;
+
+ WRITE_VIP32(VIP_CONTROL2, cw2);
+
+ return CIM_STATUS_OK;
+}
+
+/*---------------------------------------------------------------------------
+ * vip_get_power_characteristics
+ *
+ * This routine returns the current VIP clock gating state in a VIPPOWERBUFFER.
+ *---------------------------------------------------------------------------*/
+
+int vip_get_power_characteristics(VIPPOWERBUFFER *buffer)
+{
+ Q_WORD q_word;
+
+ if (!buffer)
+ return CIM_STATUS_INVALIDPARAMS;
+
+ /* READ THE EXISTING STATE */
+
+ msr_read64(MSR_DEVICE_GEODELX_VIP, MSR_GEODELINK_PM, &q_word);
+
+ /* DECODE THE CLOCK GATING BITS */
+
+ buffer->glink_clock_mode = (int)(q_word.low & VIP_MSR_POWER_GLINK);
+ buffer->vip_clock_mode = (int)(q_word.low & VIP_MSR_POWER_CLOCK);
+
+ return CIM_STATUS_OK;
+}
+
+/*---------------------------------------------------------------------------
+ * vip_get_priority_characteristics
+ *
+ * This routine returns the priority characteristics in the supplied
+ * VIPPRIORITYBUFFER.
+ *---------------------------------------------------------------------------*/
+
+int vip_get_priority_characteristics(VIPPRIORITYBUFFER *buffer)
+{
+ Q_WORD q_word;
+
+ if (!buffer)
+ return CIM_STATUS_INVALIDPARAMS;
+
+ /* READ THE CURRENT STATE */
+
+ msr_read64 (MSR_DEVICE_GEODELX_VIP, MSR_GEODELINK_CONFIG, &q_word);
+
+ /* DECODE THE PRIORITIES */
+
+ buffer->secondary = (q_word.low & VIP_MSR_MCR_SECOND_PRIORITY_MASK) >> VIP_MSR_MCR_SECOND_PRIORITY_SHIFT;
+ buffer->primary = (q_word.low & VIP_MSR_MCR_PRIMARY_PRIORITY_MASK) >> VIP_MSR_MCR_PRIMARY_PRIORITY_SHIFT;
+ buffer->pid = q_word.low & VIP_MSR_MCR_PID_MASK;
+
+ return CIM_STATUS_OK;
+}
+
+/*---------------------------------------------------------------------------
+ * vip_get_capability_characteristics
+ *
+ * This routine returns revision information for the device.
+ *---------------------------------------------------------------------------*/
+
+int vip_get_capability_characteristics(VIPCAPABILITIESBUFFER *buffer)
+{
+ Q_WORD q_word ;
+
+ if (!buffer)
+ return CIM_STATUS_INVALIDPARAMS;
+
+ /* READ THE CURRENT MSR CONTENTS */
+
+ msr_read64 (MSR_DEVICE_GEODELX_VIP, MSR_GEODELINK_CAP, &q_word);
+
+ /* DECODE THE REVISIONS */
+
+ buffer->revision_id = (q_word.low & VIP_MSR_CAP_REVID_MASK) >> VIP_MSR_CAP_REVID_SHIFT;
+ buffer->device_id = (q_word.low & VIP_MSR_CAP_DEVID_MASK) >> VIP_MSR_CAP_DEVID_SHIFT;
+ buffer->n_clock_domains = (q_word.low & VIP_MSR_CAP_NCLK_MASK) >> VIP_MSR_CAP_NCLK_SHIFT;
+ buffer->n_smi_registers = (q_word.low & VIP_MSR_CAP_NSMI_MASK) >> VIP_MSR_CAP_NSMI_SHIFT;
+
+ return CIM_STATUS_OK;
+}
+
+
+
+#endif
diff -Nru kernel-2.6.18geode-hurricane.orig/lib/cimarron/cim/cim_vop.c kernel-2.6.18geode-hurricane/lib/cimarron/cim/cim_vop.c
--- kernel-2.6.18geode-hurricane.orig/lib/cimarron/cim/cim_vop.c 1970-01-01 01:00:00.000000000 +0100
+++ kernel-2.6.18geode-hurricane/lib/cimarron/cim/cim_vop.c 2006-12-01 13:21:21.000000000 +0100
@@ -0,0 +1,564 @@
+ /*
+ *
+ * Copyright (C) 2005 Advanced Micro Devices, Inc. All Rights Reserved.
+ *
+ *
+ *
+ *
+ *
+ *
+ * Cimarron VOP configuration routines.
+ *
+ *
+ */
+
+/*---------------------------------------------------------------------------
+ * vop_set_vbi_window
+ *
+ * This routine configures the output position and location in memory of
+ * VBI data.
+ *---------------------------------------------------------------------------*/
+
+int vop_set_vbi_window (VOPVBIWINDOWBUFFER *buffer)
+{
+ unsigned long unlock, temp;
+ unsigned long hstart, hstop;
+ unsigned long htotal, hsyncstart;
+
+ if (!buffer)
+ return CIM_STATUS_INVALIDPARAMS;
+
+ unlock = READ_REG32 (DC3_UNLOCK);
+ WRITE_REG32 (DC3_UNLOCK, DC3_UNLOCK_VALUE);
+
+ /* PROGRAM HORIZONTAL POSITION */
+ /* The horizontal position is a little tricky. The counter for the horizontal */
+ /* timings is reused for the VBI counter. Consequently, the horizontal start */
+ /* and stop values are based off the beginning of active data. However, the */
+ /* VG has a quirk. If the counter start position is before the beginning of */
+ /* HSync, it applies to the previous line. If the counter is after the */
+ /* beginning of HSync it applies to the current line. So, for one line */
+ /* the real range can be thought of as HSync_start to (HSync_start + htotal - 1). */
+ /* However, the counters must be between 0 and htotal - 1. When placing VBI */
+ /* data before the start of active data, the horizontal end position will thus */
+ /* be *less* than the horizontal start. */
+
+ htotal = ((READ_REG32 (DC3_H_ACTIVE_TIMING) >> 16) & 0xFFF) + 1;
+ hsyncstart = (READ_REG32 (DC3_H_SYNC_TIMING) & 0xFFF) + 1;
+
+ if (buffer->horz_from_hsync)
+ {
+ /* VERIFY THAT THE INPUT IS VALID */
+
+ if (buffer->horz_start < 0 || (buffer->horz_start + buffer->vbi_width) > htotal)
+ return CIM_STATUS_INVALIDPARAMS;
+
+ hstart = buffer->horz_start + hsyncstart;
+ }
+ else
+ {
+ /* VERIFY THAT THE INPUT IS VALID */
+
+ if (buffer->horz_start < ((long)hsyncstart - (long)htotal) ||
+ buffer->horz_start > (long)hsyncstart ||
+ buffer->vbi_width > htotal)
+ {
+ return CIM_STATUS_INVALIDPARAMS;
+ }
+
+ hstart = buffer->horz_start + htotal;
+ }
+
+ hstop = hstart + buffer->vbi_width;
+ if (hstart > htotal) hstart -= htotal;
+ if (hstop > htotal) hstop -= htotal;
+ hstart--;
+ hstop--;
+ WRITE_REG32 (DC3_VBI_HOR, ((hstop << DC3_VBI_HOR_END_SHIFT) & DC3_VBI_HOR_END_MASK) |
+ (hstart & DC3_VBI_HOR_START_MASK));
+
+ /* WRITE LINE CAPTURE MASKS */
+
+ WRITE_REG32 (DC3_VBI_LN_ODD, ((buffer->odd_line_offset << DC3_VBI_ODD_LINE_SHIFT) & DC3_VBI_ODD_LINE_MASK) |
+ (buffer->odd_line_capture_mask & DC3_VBI_ODD_ENABLE_MASK));
+
+ WRITE_REG32 (DC3_VBI_LN_EVEN, ((buffer->even_line_offset << DC3_VBI_EVEN_LINE_SHIFT) & DC3_VBI_EVEN_LINE_MASK) |
+ (buffer->even_line_capture_mask & DC3_VBI_EVEN_ENABLE_MASK));
+
+ /* PROGRAM SOURCE OFFSETS */
+ /* Start with the even offsets. Note that we always enable 16-bit VBI, as this */
+ /* is the only way to get VBI data on each VOP clock. */
+
+ temp = READ_REG32 (DC3_VBI_EVEN_CTL) & ~DC3_VBI_EVEN_CTL_OFFSET_MASK;
+ temp |= DC3_VBI_EVEN_CTL_ENABLE_16;
+ if (buffer->enable_upscale)
+ temp |= DC3_VBI_EVEN_CTL_UPSCALE;
+ WRITE_REG32 (DC3_VBI_EVEN_CTL, temp | (buffer->even_address_offset & DC3_VBI_EVEN_CTL_OFFSET_MASK));
+
+ /* ODD OFFSET */
+
+ temp = READ_REG32 (DC3_VBI_ODD_CTL) & ~DC3_VBI_ODD_CTL_OFFSET_MASK;
+ WRITE_REG32 (DC3_VBI_ODD_CTL, temp | (buffer->odd_address_offset & DC3_VBI_ODD_CTL_OFFSET_MASK));
+
+ /* PITCH */
+
+ temp = ((buffer->data_size >> 3) << 16) | ((buffer->data_pitch >> 3) & 0x0000FFFF);
+ WRITE_REG32(DC3_VBI_PITCH, temp);
+
+ WRITE_REG32 (DC3_UNLOCK, unlock);
+
+ return CIM_STATUS_OK;
+}
+
+/*---------------------------------------------------------------------------
+ * vop_enable_vbi_output
+ *
+ * This routine enables/disables VBI fetching inside the video generator.
+ *---------------------------------------------------------------------------*/
+
+int vop_enable_vbi_output (int enable)
+{
+ unsigned long unlock, temp;
+
+ unlock = READ_REG32 (DC3_UNLOCK);
+ temp = READ_REG32 (DC3_VBI_EVEN_CTL);
+
+ if (enable) temp |= DC3_VBI_ENABLE;
+ else temp &= ~DC3_VBI_ENABLE;
+
+ WRITE_REG32 (DC3_UNLOCK, DC3_UNLOCK_VALUE);
+ WRITE_REG32 (DC3_VBI_EVEN_CTL, temp);
+ WRITE_REG32 (DC3_UNLOCK, unlock);
+
+ return CIM_STATUS_OK;
+}
+
+/*---------------------------------------------------------------------------
+ * vop_set_configuration
+ *
+ * This routine is passed a VOP_CONFIGURATION structure that contains all
+ * the necessary information to configure VOP output.
+ *---------------------------------------------------------------------------*/
+
+int vop_set_configuration (VOPCONFIGURATIONBUFFER *config)
+{
+ unsigned long vop_config = 0;
+ unsigned long alpha, control2;
+ unsigned long unlock;
+ unsigned long delta;
+ Q_WORD msr_value;
+ int rgb = 0;
+
+ if (!config)
+ return CIM_STATUS_INVALIDPARAMS;
+
+ unlock = READ_REG32 (DC3_UNLOCK);
+ delta = READ_REG32 (DC3_VID_DS_DELTA) & DC3_DS_DELTA_MASK;
+
+ /* OVERRIDE THE OUTPUT SETTINGS TO ENABLE VOP OUTPUT */
+
+ if (config->mode != VOP_MODE_DISABLED)
+ {
+ msr_read64 (MSR_DEVICE_GEODELX_DF, MSR_GEODELINK_CONFIG, &msr_value);
+ msr_value.low &= ~DF_CONFIG_OUTPUT_MASK;
+ msr_value.low |= DF_OUTPUT_VOP;
+ msr_write64 (MSR_DEVICE_GEODELX_DF, MSR_GEODELINK_CONFIG, &msr_value);
+ }
+
+ /* SET THE UNIVERSAL VOP OPTIONS */
+
+ if (config->flags & VOP_FLAG_SWAP_UV) vop_config |= VOP_CONFIG_SWAPUV;
+ if (config->flags & VOP_FLAG_SWAP_VBI) vop_config |= VOP_CONFIG_SWAPVBI;
+
+ /* SET THE MODE SPECIFIC PARAMETERS */
+
+ if (config->mode == VOP_MODE_601)
+ {
+ vop_config |= config->vop601.flags;
+ vop_config |= config->vop601.vsync_shift;
+ vop_config |= VOP_CONFIG_ENABLE_601 | VOP_CONFIG_VIP2_0;
+
+ switch (config->vop601.output_mode)
+ {
+ case VOP_601_YUV_16BIT:
+ vop_config |= VOP_CONFIG_VIP2_16BIT;
+ break;
+ case VOP_601_YUV_4_4_4:
+ vop_config |= VOP_CONFIG_DISABLE_DECIMATE;
+ break;
+ case VOP_601_RGB_8_8_8:
+ vop_config |= VOP_CONFIG_DISABLE_DECIMATE | VOP_CONFIG_RGBMODE;
+ rgb = 1;
+ break;
+ }
+
+ if (config->vop601.vsync_shift == VOP_VSYNC_LATER_BY_X)
+ {
+ delta |= (config->vop601.vsync_shift_count & DC3_601_VSYNC_SHIFT_MASK);
+ delta |= DC3_601_VSYNC_SHIFT_ENABLE;
+ }
+ }
+ else
+ {
+ if (config->flags & VOP_FLAG_VBI) vop_config |= VOP_CONFIG_VBI;
+ if (config->flags & VOP_FLAG_TASK) vop_config |= VOP_CONFIG_TASK;
+ if (config->flags & VOP_FLAG_SINGLECHIPCOMPAT) vop_config |= VOP_CONFIG_SC_COMPATIBLE;
+ if (config->flags & VOP_FLAG_EXTENDEDSAV) vop_config |= VOP_CONFIG_EXTENDED_SAV;
+
+ switch (config->mode)
+ {
+ case VOP_MODE_DISABLED:
+ vop_config |= VOP_CONFIG_DISABLED;
+ break;
+ case VOP_MODE_VIP11:
+ vop_config |= VOP_CONFIG_VIP1_1;
+ break;
+ case VOP_MODE_CCIR656:
+ vop_config |= VOP_CONFIG_CCIR656;
+ break;
+ case VOP_MODE_VIP20_8BIT:
+ vop_config |= VOP_CONFIG_VIP2_0;
+ break;
+ case VOP_MODE_VIP20_16BIT:
+ vop_config |= VOP_CONFIG_VIP2_0 | VOP_CONFIG_VIP2_16BIT;
+ break;
+ }
+ }
+
+ /* SET THE 4:4:4 TO 4:2:2 DECIMATION ALGORITHM */
+
+ vop_config |= (config->conversion_mode);
+
+ /* SET THE VSYNC OUT OPTIONS */
+
+ control2 = READ_VIP32 (VIP_CONTROL2) & ~VIP_CONTROL2_SYNC2PIN_MASK;
+ control2 |= config->vsync_out;
+ WRITE_VIP32 (VIP_CONTROL2, control2);
+
+ /* FORCE THE CORRECT VOP COLOR SPACE */
+ /* The output of the mixer will be either RGB or YUV. We must enable */
+ /* or disable the VOP CSC based on the desired output format. */
+
+ alpha = READ_VID32 (DF_VID_ALPHA_CONTROL);
+ if (!(alpha & DF_CSC_GRAPHICS_RGB_TO_YUV))
+ {
+ /* RGB OUTPUT FROM THE MIXER */
+
+ if (!rgb) alpha |= DF_CSC_VOP_RGB_TO_YUV;
+ else alpha &= ~DF_CSC_VOP_RGB_TO_YUV;
+ }
+ else
+ {
+ /* YUV OUTPUT FROM THE MIXER */
+ /* As there is no YUV->RGB VOP conversion, we simply disable the */
+ /* VOP CSC and trust that the user is competent. */
+
+ alpha &= ~DF_CSC_VOP_RGB_TO_YUV;
+ }
+
+ /* AND WRITE THE CONFIGURATION */
+
+ WRITE_VID32 (DF_VID_ALPHA_CONTROL, alpha);
+ WRITE_VOP32(VOP_CONFIGURATION, vop_config);
+ WRITE_REG32 (DC3_UNLOCK, DC3_UNLOCK_VALUE);
+ WRITE_REG32 (DC3_VID_DS_DELTA, delta);
+ WRITE_REG32 (DC3_UNLOCK, unlock);
+
+ return CIM_STATUS_OK;
+}
+
+/*---------------------------------------------------------------------------
+ * vop_save_state
+ *
+ * This routine saves the necessary register contents in order to restore
+ * at a later point to the same state. Note that the capture state is
+ * forced to OFF in this routine.
+ *---------------------------------------------------------------------------*/
+
+int vop_save_state (VOPSTATEBUFFER *save_buffer)
+{
+ if (!save_buffer)
+ return CIM_STATUS_INVALIDPARAMS;
+
+ save_buffer->config = READ_VOP32(VOP_CONFIGURATION);
+
+ return CIM_STATUS_OK;
+}
+
+/*---------------------------------------------------------------------------
+ * vop_restore_state
+ *
+ * This routine restores the state of the vop registers - which were
+ * previously saved using vop_save_state.
+ *---------------------------------------------------------------------------*/
+
+int vop_restore_state (VOPSTATEBUFFER *restore_buffer)
+{
+ if (!restore_buffer)
+ return CIM_STATUS_INVALIDPARAMS;
+
+ WRITE_VOP32(VOP_CONFIGURATION, restore_buffer->config);
+
+ return CIM_STATUS_OK;
+}
+
+/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ * CIMARRON VOP READ ROUTINES
+ * These routines are included for use in diagnostics or when debugging. They
+ * can be optionally excluded from a project.
+ *+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
+
+#if CIMARRON_INCLUDE_VOP_READ_ROUTINES
+
+/*---------------------------------------------------------------------------
+ * vop_get_current_mode
+ *
+ * This routine reads the current VIP operating mode and stores it in the
+ * passed VOP_CONFIGURATION structure.
+ *---------------------------------------------------------------------------*/
+
+int vop_get_current_mode (VOPCONFIGURATIONBUFFER *config)
+{
+ unsigned long vop_config = 0;
+ unsigned long alpha;
+
+ if (!config)
+ return CIM_STATUS_INVALIDPARAMS;
+
+ vop_config = READ_VOP32 (VOP_CONFIGURATION);
+ alpha = READ_VID32 (DF_VID_ALPHA_CONTROL);
+
+ /* READ THE CURRENT MODE */
+
+ switch (vop_config & VOP_CONFIG_MODE_MASK)
+ {
+ case VOP_CONFIG_DISABLED: config->mode = VOP_MODE_DISABLED; break;
+ case VOP_CONFIG_VIP1_1: config->mode = VOP_MODE_VIP11; break;
+ case VOP_CONFIG_CCIR656: config->mode = VOP_MODE_CCIR656; break;
+ case VOP_CONFIG_VIP2_0:
+
+ if (vop_config & VOP_CONFIG_ENABLE_601)
+ config->mode = VOP_MODE_601;
+ else if (vop_config & VOP_CONFIG_VIP2_16BIT)
+ config->mode = VOP_MODE_VIP20_16BIT;
+ else
+ config->mode = VOP_MODE_VIP20_8BIT;
+ break;
+ }
+
+ /* READ 601 SETTINGS */
+
+ config->vop601.flags = vop_config & (VOP_CONFIG_INVERT_DISPE |
+ VOP_CONFIG_INVERT_HSYNC | VOP_CONFIG_INVERT_VSYNC);
+
+ config->vop601.vsync_shift = vop_config & VOP_CONFIG_VSYNC_MASK;
+ config->vop601.vsync_shift_count = READ_REG32 (DC3_VID_DS_DELTA) & DC3_601_VSYNC_SHIFT_MASK;
+
+ if ((alpha & DF_CSC_GRAPHICS_RGB_TO_YUV) ||
+ (alpha & DF_CSC_VOP_RGB_TO_YUV))
+ {
+ /* YUV OUTPUT */
+
+ if (vop_config & VOP_CONFIG_DISABLE_DECIMATE)
+ config->vop601.output_mode = VOP_601_YUV_4_4_4;
+ else if (vop_config & VOP_CONFIG_VIP2_16BIT)
+ config->vop601.output_mode = VOP_601_YUV_16BIT;
+ else
+ config->vop601.output_mode = VOP_601_YUV_8BIT;
+ }
+ else
+ {
+ config->vop601.output_mode = VOP_601_RGB_8_8_8;
+ }
+
+ config->flags = 0;
+
+ /* READ THE UNIVERSAL VOP OPTIONS */
+
+ if (vop_config & VOP_CONFIG_SWAPUV) config->flags |= VOP_FLAG_SWAP_UV;
+ if (vop_config & VOP_CONFIG_SWAPVBI) config->flags |= VOP_FLAG_SWAP_VBI;
+ if (vop_config & VOP_CONFIG_VBI) config->flags |= VOP_FLAG_VBI;
+ if (vop_config & VOP_CONFIG_TASK) config->flags |= VOP_FLAG_TASK;
+ if (vop_config & VOP_CONFIG_SC_COMPATIBLE) config->flags |= VOP_FLAG_SINGLECHIPCOMPAT;
+ if (vop_config & VOP_CONFIG_EXTENDED_SAV) config->flags |= VOP_FLAG_EXTENDEDSAV;
+
+ config->conversion_mode = vop_config & VOP_CONFIG_422_MASK;
+
+ config->vsync_out = READ_VIP32 (VIP_CONTROL2) & VIP_CONTROL2_SYNC2PIN_MASK;
+
+ return CIM_STATUS_OK;
+}
+
+/*---------------------------------------------------------------------------
+ * vop_get_vbi_window
+ *
+ * This routine reads the current VBI configuration for VOP output.
+ *---------------------------------------------------------------------------*/
+
+int vop_get_vbi_configuration (VOPVBIWINDOWBUFFER *buffer)
+{
+ unsigned long temp;
+ unsigned long hstart, hstop;
+ unsigned long htotal, hsyncstart;
+
+ if (!buffer)
+ return CIM_STATUS_INVALIDPARAMS;
+
+ htotal = ((READ_REG32 (DC3_H_ACTIVE_TIMING) >> 16) & 0xFFF) + 1;
+ hsyncstart = (READ_REG32 (DC3_H_SYNC_TIMING) & 0xFFF) + 1;
+
+ /* DECODE HORIZONTAL POSITION */
+ /* This is done according to the requested horizontal origin */
+
+ temp = READ_REG32 (DC3_VBI_HOR);
+ hstart = (temp & DC3_VBI_HOR_START_MASK) + 1;
+ hstop = ((temp & DC3_VBI_HOR_END_MASK) >> DC3_VBI_HOR_END_SHIFT) + 1;
+ if (buffer->horz_from_hsync)
+ {
+ buffer->horz_start = hstart + htotal - hsyncstart;
+ if (buffer->horz_start >= (long)htotal)
+ buffer->horz_start -= htotal;
+ }
+ else
+ {
+ if (hstart > hsyncstart)
+ buffer->horz_start = (long)hstart - (long)htotal;
+ else
+ buffer->horz_start = hstart;
+ }
+
+ if (hstop > hstart)
+ buffer->vbi_width = hstop - hstart;
+ else
+ buffer->vbi_width = (htotal - hstart) + hstop;
+
+ /* READ LINE MASKS */
+
+ temp = READ_REG32 (DC3_VBI_LN_ODD);
+ buffer->odd_line_offset = (temp & DC3_VBI_ODD_LINE_MASK) >> DC3_VBI_ODD_LINE_SHIFT;
+ buffer->odd_line_capture_mask = (temp & DC3_VBI_ODD_ENABLE_MASK);
+
+ temp = READ_REG32 (DC3_VBI_LN_EVEN);
+ buffer->even_line_offset = (temp & DC3_VBI_EVEN_LINE_MASK) >> DC3_VBI_EVEN_LINE_SHIFT;
+ buffer->even_line_capture_mask = (temp & DC3_VBI_EVEN_ENABLE_MASK);
+
+ /* READ VBI UPSCALE SETTINGS */
+
+ buffer->enable_upscale = 0;
+ temp = READ_REG32 (DC3_VBI_EVEN_CTL);
+ if (temp & DC3_VBI_EVEN_CTL_UPSCALE)
+ buffer->enable_upscale = 1;
+
+ /* READ SOURCE OFFSETS */
+
+ buffer->even_address_offset = temp & DC3_VBI_EVEN_CTL_OFFSET_MASK;
+ buffer->odd_address_offset = READ_REG32 (DC3_VBI_ODD_CTL) & DC3_VBI_ODD_CTL_OFFSET_MASK;
+
+ /* PITCH AND SIZE */
+
+ temp = READ_REG32 (DC3_VBI_PITCH);
+ buffer->data_size = (temp >> 16) << 3;
+ buffer->data_pitch = (temp & 0xFFFF);
+
+ return CIM_STATUS_OK;
+}
+
+/*---------------------------------------------------------------------------
+ * vop_get_vbi_enable
+ *
+ * This routine reads the current enable status of VBI output.
+ *---------------------------------------------------------------------------*/
+
+int vop_get_vbi_enable (void)
+{
+ if (READ_REG32 (DC3_VBI_EVEN_CTL) & DC3_VBI_ENABLE)
+ return 1;
+
+ return 0;
+}
+
+/*---------------------------------------------------------------------------
+ * vop_get_crc
+ *
+ * This routine returns a CRC of the current VOP data
+ ---------------------------------------------------------------------------*/
+
+unsigned long vop_get_crc(void)
+{
+ unsigned long crc;
+ unsigned long config = READ_VOP32(VOP_CONFIGURATION);
+ unsigned long timeout = 1000;
+
+ if (!(READ_REG32 (DC3_DISPLAY_CFG) & DC3_DCFG_TGEN))
+ return 0xFFFFFFFF;
+
+ /* RESET CRC */
+
+ WRITE_VOP32 (VOP_CONFIGURATION, config & ~VOP_CONFIG_ENABLE_SIGNATURE);
+
+ /* WAIT FOR THE RESET TO BE LATCHED */
+
+ while ((READ_VOP32 (VOP_SIGNATURE) != 0x00000001) && timeout)
+ timeout--;
+
+ WRITE_VOP32 (VOP_CONFIGURATION, config | VOP_CONFIG_ENABLE_SIGNATURE);
+
+ /* WAIT UNTIL NOT ACTIVE, THEN ACTIVE, NOT ACTIVE, THEN ACTIVE */
+
+ while (!(READ_VOP32 (VOP_CONFIGURATION) & VOP_CONFIG_SIGVAL))
+ ;
+
+ crc = READ_VOP32 (VOP_SIGNATURE);
+
+ return crc;
+}
+
+/*---------------------------------------------------------------------------
+ * vop_read_vbi_crc
+ *
+ * This routine returns a CRC of the current VBI data
+ ---------------------------------------------------------------------------*/
+
+unsigned long vop_read_vbi_crc(void)
+{
+ unsigned long gcfg, unlock, vbi_even;
+ unsigned long crc;
+
+ if (!(READ_REG32 (DC3_DISPLAY_CFG) & DC3_DCFG_TGEN) ||
+ !(READ_REG32 (DC3_VBI_EVEN_CTL) & DC3_VBI_ENABLE))
+ {
+ return 0xFFFFFFFF;
+ }
+
+ unlock = READ_REG32 (DC3_UNLOCK);
+ gcfg = READ_REG32 (DC3_GENERAL_CFG);
+ vbi_even = READ_REG32 (DC3_VBI_EVEN_CTL);
+
+ gcfg |= DC3_GCFG_SGRE | DC3_GCFG_CRC_MODE;
+ gcfg &= ~(DC3_GCFG_SGFR | DC3_GCFG_SIG_SEL);
+ vbi_even |= DC3_VBI_EVEN_ENABLE_CRC;
+
+ WRITE_REG32 (DC3_UNLOCK, DC3_UNLOCK_VALUE);
+ WRITE_REG32 (DC3_VBI_EVEN_CTL, vbi_even);
+ WRITE_REG32 (DC3_GENERAL_CFG, gcfg & ~DC3_GCFG_SIGE);
+ WRITE_REG32 (DC3_GENERAL_CFG, gcfg | DC3_GCFG_SIGE);
+
+ /* WAIT FOR THE CRC TO BE COMPLETED */
+
+ while (!(READ_REG32 (DC3_LINE_CNT_STATUS) & DC3_LNCNT_SIGC))
+ ;
+
+ /* READ THE COMPLETED CRC */
+
+ crc = READ_REG32 (DC3_PAL_DATA);
+
+ /* RESTORE THE PALETTE SETTINGS */
+
+ gcfg &= ~DC3_GCFG_SGRE;
+ WRITE_REG32 (DC3_GENERAL_CFG, gcfg);
+ WRITE_REG32 (DC3_UNLOCK, unlock);
+
+ return crc;
+}
+
+#endif
diff -Nru kernel-2.6.18geode-hurricane.orig/lib/cimarron/cimapi.c kernel-2.6.18geode-hurricane/lib/cimarron/cimapi.c
--- kernel-2.6.18geode-hurricane.orig/lib/cimarron/cimapi.c 1970-01-01 01:00:00.000000000 +0100
+++ kernel-2.6.18geode-hurricane/lib/cimarron/cimapi.c 2006-12-01 13:21:21.000000000 +0100
@@ -0,0 +1,509 @@
+/*
+ * 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
+ * */
+/*
+ * */
+/*
+ * Base include file for the Cimarron library. This file should be modified
+ * and included in any Cimarron-based project.
+ * */
+
+/*----------------------------------------------------------------------*/
+/* MODULE SETTINGS */
+/* The following #defines affect which modules are included in the */
+/* project. */
+/*----------------------------------------------------------------------*/
+
+#define CIMARRON_INCLUDE_GP 1
+#define CIMARRON_INCLUDE_VG 1
+#define CIMARRON_INCLUDE_VIP 1
+#define CIMARRON_INCLUDE_VOP 1
+#define CIMARRON_INCLUDE_VIDEO 1
+#define CIMARRON_INCLUDE_INIT 1
+
+#define CIMARRON_INCLUDE_VG_READ_ROUTINES 1
+#define CIMARRON_INCLUDE_DF_READ_ROUTINES 1
+#define CIMARRON_INCLUDE_VIP_READ_ROUTINES 1
+#define CIMARRON_INCLUDE_VOP_READ_ROUTINES 1
+
+/*----------------------------------------------------------------------*/
+/* HARDWARE ACCESS SETTINGS */
+/* The following #defines affect how the Cimarron macros access the */
+/* hardware. The hardware access macros are broken up into groups. */
+/* Each group includes an enabling #define as well as several #define */
+/* options that modify the macro configuration that is included. */
+/* If the enabling define is deleted or all options are set to 0, the */
+/* corresponding macros must be implemented by the user. The */
+/* combinations are explained as follows: */
+/* must be manually defined by the user. This allows a user to use the */
+/* cim_defs.h file for only those macros that suit the needs of his/her */
+/* project. For example, a user may need custom implementations of the */
+/* I/O and MSR macros, but may still want to use the default macros to */
+/* read and write hardware registers. The combinations are explained as */
+/* follows: */
+/* */
+/* Register Group: */
+/* Disabling define: */
+/* CIMARRON_EXCLUDE_REGISTER_ACCESS_MACROS */
+/* Define this setting to exclude the register access macros. */
+/* This setting is the inverse of the other group settings in */
+/* that these macros are included by default. This allows the */
+/* cim_defs.h file to be included outside of cimarron.c for */
+/* basic operations. */
+/* */
+/* Memory Group: */
+/* Enabling define: */
+/* CIMARRON_INCLUDE_STRING_MACROS */
+/* Options: */
+/* CIMARRON_OPTIMIZE_ASSEMBLY */
+/* Set to 1 to allow the use of inline assembly when writing */
+/* large chunks of data to memory. Essentially, this allows */
+/* a rep movsd in place of a slower C for-loop. */
+/* CIMARRON_OPTIMIZE_FORLOOP */
+/* Define for C only data writes. */
+/* */
+/* MSR Group: */
+/* Enabling define: */
+/* CIMARRON_INCLUDE_MSR_MACROS */
+/* Options: */
+/* CIMARRON_MSR_DIRECT_ASM */
+/* Set to 1 to allow the use of the rdmsr and wrmsr opcodes in */
+/* inline assembly. */
+/* CIMARRON_MSR_VSA_IO */
+/* Set to 1 to access MSRs using a VSAII virtual register. */
+/* CIMARRON_MSR_KERNEL_ROUTINE */
+/* Set to 1 to access MSRs using a wrapper routine in the */
+/* Linux kernel. */
+/* */
+/* IO Group: */
+/* Enabling define: */
+/* CIMARRON_INCLUDE_IO_MACROS */
+/* Options: */
+/* CIMARRON_IO_DIRECT_ACCESS */
+/* Set to 1 to perform IO accesses using inline assembly. */
+/* CIMARRON_IO_ABSTRACTED_ASM */
+/* Set to 1 to perform IO using abstracted IO in Linux. */
+/* */
+/* Custom Group: */
+/* Disabling define: */
+/* CIMARRON_EXCLUDE_CUSTOM_MACROS */
+/* By default, the custom macros (the macros used by */
+/* gp_custom_convert_blt) are mapped to the normal command */
+/* string macros. Setting this to 1 allows the user to */
+/* create a custom implementation. */
+/*----------------------------------------------------------------------*/
+
+/* UNCOMMENT THE FOLLOWING LINE TO EXCLUDE BASIC REGISTER ACCESS MACROS */
+
+/* #define CIMARRON_EXCLUDE_REGISTER_ACCESS_MACROS */
+
+#define CIMARRON_INCLUDE_STRING_MACROS
+#define CIMARRON_OPTIMIZE_ASSEMBLY 0
+#define CIMARRON_OPTIMIZE_FORLOOP 0
+#define CIMARRON_OPTIMIZE_ABSTRACTED_ASM 1
+
+#define CIMARRON_INCLUDE_MSR_MACROS
+#define CIMARRON_MSR_DIRECT_ASM 0
+#define CIMARRON_MSR_VSA_IO 0
+#define CIMARRON_MSR_ABSTRACTED_ASM 1
+#define CIMARRON_MSR_KERNEL_ROUTINE 0
+
+#define CIMARRON_INCLUDE_IO_MACROS
+#define CIMARRON_IO_DIRECT_ACCESS 0
+#define CIMARRON_IO_ABSTRACTED_ASM 1
+
+/* UNCOMMENT THE FOLLOWING LINE TO IMPLEMENT CUSTOM MACROS FOR GP_CUSTOM_CONVERT_BLT */
+
+/* #define CIMARRON_EXCLUDE_CUSTOM_MACROS */
+
+/*----------------------------------------------------------------------*/
+/* MODULE VARIABLES */
+/* The following #defines affect how global variables in each Cimarron */
+/* module are defined. These variables can be made static (to prevent */
+/* naming conflicts) or they can be defined without the static keyword */
+/* (to allow extern references). */
+/*----------------------------------------------------------------------*/
+
+#if 1
+#define CIMARRON_STATIC static
+#else
+#define CIMARRON_STATIC
+#endif
+
+/*----------------------------------------------------------------------*/
+/* CIMARRON GLOBAL VARIABLES */
+/* These globals are used by the hardware access macros. They must be */
+/* initialized by the application to point to the memory-mapped */
+/* registers of their respective blocks. */
+/*----------------------------------------------------------------------*/
+
+unsigned char *cim_gp_ptr = (unsigned char *)0;
+unsigned char *cim_fb_ptr = (unsigned char *)0;
+unsigned char *cim_cmd_base_ptr = (unsigned char *)0;
+unsigned char *cim_cmd_ptr = (unsigned char *)0;
+unsigned char *cim_vid_ptr = (unsigned char *)0;
+unsigned char *cim_vip_ptr = (unsigned char *)0;
+unsigned char *cim_vg_ptr = (unsigned char *)0;
+
+/*----------------------------------------------------------------------*/
+/* INCLUDE RELEVANT CIMARRON HEADERS */
+/*----------------------------------------------------------------------*/
+
+/* HARDWARE REGISTER DEFINITIONS */
+
+#include "cim_regs.h"
+
+/* ROUTINE DEFINITIONS */
+/* All routines have a prototype, even those that are not included */
+/* via #ifdefs. This prevents the user from having to include the */
+/* correct #defines anywhere he/she wants to call a Cimarron routine. */
+
+#include "cim_rtns.h"
+
+/* HARDWARE ACCESS MACROS */
+
+#include "cim_defs.h"
+
+/*----------------------------------------------------------------------*/
+/* CIMARRON MODULES */
+/* Modules and sub-modules are included based on user settings. Note */
+/* that excluding one or more modules may result in functionality */
+/* holes. */
+/*----------------------------------------------------------------------*/
+
+/* GRAPHICS PROCESSOR */
+
+#if CIMARRON_INCLUDE_GP
+#include "cim_gp.c"
+#endif
+
+/* VIDEO GENERATOR */
+
+#if CIMARRON_INCLUDE_VG
+#include "cim_modes.c"
+#include "cim_vg.c"
+#endif
+
+/* DISPLAY FILTER */
+
+#if CIMARRON_INCLUDE_VIDEO
+#include "cim_filter.c"
+#include "cim_df.c"
+#endif
+
+/* INITIALIZATION AND DETECTION */
+
+#if CIMARRON_INCLUDE_INIT
+#include "cim_init.c"
+#endif
+
+/* VIP SUPPORT */
+
+#if CIMARRON_INCLUDE_VIP
+#include "cim_vip.c"
+#endif
+
+/* VOP SUPPORT */
+
+#if CIMARRON_INCLUDE_VOP
+#include "cim_vop.c"
+#endif
+
+/* MSR ACCESS */
+/* This module is used to access machine-specific registers. */
+/* It cannot be excluded from a project. */
+
+#include "cim_msr.c"
+
+/* LINUX SPECIFIC ADDITIONS */
+
+#include
+
+/* cim_msr.c */
+EXPORT_SYMBOL(msr_init_table);
+EXPORT_SYMBOL(msr_create_geodelink_table);
+EXPORT_SYMBOL(msr_create_device_list);
+EXPORT_SYMBOL(msr_read64);
+EXPORT_SYMBOL(msr_write64);
+
+EXPORT_SYMBOL(cim_inb);
+EXPORT_SYMBOL(cim_inw);
+EXPORT_SYMBOL(cim_outb);
+EXPORT_SYMBOL(cim_outw);
+
+/* cim_df.c */
+
+#if CIMARRON_INCLUDE_VIDEO
+
+EXPORT_SYMBOL(df_set_crt_enable);
+EXPORT_SYMBOL(df_set_panel_enable);
+EXPORT_SYMBOL(df_configure_video_source);
+EXPORT_SYMBOL(df_set_video_offsets);
+EXPORT_SYMBOL(df_set_video_scale);
+EXPORT_SYMBOL(df_set_video_position);
+EXPORT_SYMBOL(df_set_video_filter_coefficients);
+EXPORT_SYMBOL(df_set_video_enable);
+EXPORT_SYMBOL(df_set_video_color_key);
+EXPORT_SYMBOL(df_set_video_palette);
+EXPORT_SYMBOL(df_set_video_palette_entry);
+EXPORT_SYMBOL(df_configure_video_cursor_color_key);
+EXPORT_SYMBOL(df_set_video_cursor_color_key_enable);
+EXPORT_SYMBOL(df_configure_alpha_window);
+EXPORT_SYMBOL(df_set_alpha_window_enable);
+EXPORT_SYMBOL(df_set_no_ck_outside_alpha);
+EXPORT_SYMBOL(df_set_video_request);
+EXPORT_SYMBOL(df_set_output_color_space);
+EXPORT_SYMBOL(df_set_output_path);
+EXPORT_SYMBOL(df_test_video_flip_status);
+EXPORT_SYMBOL(df_save_state);
+EXPORT_SYMBOL(df_restore_state);
+
+#if CIMARRON_INCLUDE_DF_READ_ROUTINES
+EXPORT_SYMBOL(df_read_composite_crc);
+EXPORT_SYMBOL(df_read_composite_window_crc);
+EXPORT_SYMBOL(df_read_panel_crc);
+EXPORT_SYMBOL(df_get_video_enable);
+EXPORT_SYMBOL(df_get_video_source_configuration);
+EXPORT_SYMBOL(df_get_video_position);
+EXPORT_SYMBOL(df_get_video_scale);
+EXPORT_SYMBOL(df_get_video_filter_coefficients);
+EXPORT_SYMBOL(df_get_video_color_key);
+EXPORT_SYMBOL(df_get_video_palette_entry);
+EXPORT_SYMBOL(df_get_video_palette);
+EXPORT_SYMBOL(df_get_video_cursor_color_key);
+EXPORT_SYMBOL(df_get_video_cursor_color_key_enable);
+EXPORT_SYMBOL(df_get_alpha_window_configuration);
+EXPORT_SYMBOL(df_get_alpha_window_enable);
+EXPORT_SYMBOL(df_get_video_request);
+EXPORT_SYMBOL(df_get_output_color_space);
+#endif
+
+#endif
+
+/* cim_gp.c */
+
+#if CIMARRON_INCLUDE_GP
+
+EXPORT_SYMBOL(gp_set_command_buffer_base);
+EXPORT_SYMBOL(gp_set_frame_buffer_base);
+EXPORT_SYMBOL(gp_set_bpp);
+EXPORT_SYMBOL(gp_declare_blt);
+EXPORT_SYMBOL(gp_declare_vector);
+EXPORT_SYMBOL(gp_write_parameters);
+EXPORT_SYMBOL(gp_set_raster_operation);
+EXPORT_SYMBOL(gp_set_alpha_operation);
+EXPORT_SYMBOL(gp_set_solid_pattern);
+EXPORT_SYMBOL(gp_set_mono_pattern);
+EXPORT_SYMBOL(gp_set_pattern_origin);
+EXPORT_SYMBOL(gp_set_color_pattern);
+EXPORT_SYMBOL(gp_set_mono_source);
+EXPORT_SYMBOL(gp_set_solid_source);
+EXPORT_SYMBOL(gp_set_source_transparency);
+EXPORT_SYMBOL(gp_program_lut);
+EXPORT_SYMBOL(gp_set_vector_pattern);
+EXPORT_SYMBOL(gp_set_strides);
+EXPORT_SYMBOL(gp_set_source_format);
+EXPORT_SYMBOL(gp_pattern_fill);
+EXPORT_SYMBOL(gp_screen_to_screen_blt);
+EXPORT_SYMBOL(gp_screen_to_screen_convert);
+EXPORT_SYMBOL(gp_color_bitmap_to_screen_blt);
+EXPORT_SYMBOL(gp_color_convert_blt);
+EXPORT_SYMBOL(gp_custom_convert_blt);
+EXPORT_SYMBOL(gp_rotate_blt);
+EXPORT_SYMBOL(gp_mono_bitmap_to_screen_blt);
+EXPORT_SYMBOL(gp_text_blt);
+EXPORT_SYMBOL(gp_mono_expand_blt);
+EXPORT_SYMBOL(gp_antialiased_text);
+EXPORT_SYMBOL(gp_masked_blt);
+EXPORT_SYMBOL(gp_screen_to_screen_masked);
+EXPORT_SYMBOL(gp_bresenham_line);
+EXPORT_SYMBOL(gp_line_from_endpoints);
+EXPORT_SYMBOL(gp_wait_until_idle);
+EXPORT_SYMBOL(gp_test_blt_busy);
+EXPORT_SYMBOL(gp_test_blt_pending);
+EXPORT_SYMBOL(gp_wait_blt_pending);
+EXPORT_SYMBOL(gp_save_state);
+EXPORT_SYMBOL(gp_restore_state);
+
+#endif
+
+/* cim_init.c */
+
+#if CIMARRON_INCLUDE_INIT
+
+EXPORT_SYMBOL(init_detect_cpu);
+EXPORT_SYMBOL(init_read_pci);
+EXPORT_SYMBOL(init_read_base_addresses);
+EXPORT_SYMBOL(init_read_cpu_frequency);
+
+#endif
+
+/* cim_vg.c */
+
+#if CIMARRON_INCLUDE_VG
+
+EXPORT_SYMBOL(vg_delay_milliseconds);
+EXPORT_SYMBOL(vg_set_display_mode);
+EXPORT_SYMBOL(vg_set_panel_mode);
+EXPORT_SYMBOL(vg_set_tv_mode);
+EXPORT_SYMBOL(vg_set_custom_mode);
+EXPORT_SYMBOL(vg_get_display_mode_index);
+EXPORT_SYMBOL(vg_get_display_mode_information);
+EXPORT_SYMBOL(vg_get_display_mode_count);
+EXPORT_SYMBOL(vg_get_current_display_mode);
+EXPORT_SYMBOL(vg_set_scaler_filter_coefficients);
+EXPORT_SYMBOL(vg_configure_flicker_filter);
+EXPORT_SYMBOL(vg_set_clock_frequency);
+EXPORT_SYMBOL(vg_set_border_color);
+EXPORT_SYMBOL(vg_set_cursor_enable);
+EXPORT_SYMBOL(vg_set_mono_cursor_colors);
+EXPORT_SYMBOL(vg_set_cursor_position);
+EXPORT_SYMBOL(vg_set_mono_cursor_shape32);
+EXPORT_SYMBOL(vg_set_mono_cursor_shape64);
+EXPORT_SYMBOL(vg_set_color_cursor_shape);
+EXPORT_SYMBOL(vg_pan_desktop);
+EXPORT_SYMBOL(vg_set_display_offset);
+EXPORT_SYMBOL(vg_set_display_pitch);
+EXPORT_SYMBOL(vg_set_display_palette_entry);
+EXPORT_SYMBOL(vg_set_display_palette);
+EXPORT_SYMBOL(vg_set_compression_enable);
+EXPORT_SYMBOL(vg_configure_compression);
+EXPORT_SYMBOL(vg_test_timing_active);
+EXPORT_SYMBOL(vg_test_vertical_active);
+EXPORT_SYMBOL(vg_wait_vertical_blank);
+EXPORT_SYMBOL(vg_configure_line_interrupt);
+EXPORT_SYMBOL(vg_test_and_clear_interrupt);
+EXPORT_SYMBOL(vg_test_flip_status);
+EXPORT_SYMBOL(vg_save_state);
+EXPORT_SYMBOL(vg_restore_state);
+
+#if CIMARRON_INCLUDE_VG_READ_ROUTINES
+EXPORT_SYMBOL(vg_read_graphics_crc);
+EXPORT_SYMBOL(vg_read_window_crc);
+EXPORT_SYMBOL(vg_get_scaler_filter_coefficients);
+EXPORT_SYMBOL(vg_get_flicker_filter_configuration);
+EXPORT_SYMBOL(vg_get_display_pitch);
+EXPORT_SYMBOL(vg_get_frame_buffer_line_size);
+EXPORT_SYMBOL(vg_get_current_vline);
+EXPORT_SYMBOL(vg_get_display_offset);
+EXPORT_SYMBOL(vg_get_cursor_info);
+EXPORT_SYMBOL(vg_get_display_palette_entry);
+EXPORT_SYMBOL(vg_get_border_color);
+EXPORT_SYMBOL(vg_get_display_palette);
+EXPORT_SYMBOL(vg_get_compression_info);
+EXPORT_SYMBOL(vg_get_compression_enable);
+EXPORT_SYMBOL(vg_get_valid_bit);
+#endif
+
+#endif
+
+#if CIMARRON_INCLUDE_VIP
+
+EXPORT_SYMBOL(vip_initialize);
+EXPORT_SYMBOL(vip_update_601_params);
+EXPORT_SYMBOL(vip_configure_capture_buffers);
+EXPORT_SYMBOL(vip_toggle_video_offsets);
+EXPORT_SYMBOL(vip_set_capture_state);
+EXPORT_SYMBOL(vip_terminate);
+EXPORT_SYMBOL(vip_configure_fifo);
+EXPORT_SYMBOL(vip_set_interrupt_enable);
+EXPORT_SYMBOL(vip_set_vsync_error);
+EXPORT_SYMBOL(vip_max_address_enable);
+EXPORT_SYMBOL(vip_set_loopback_enable);
+EXPORT_SYMBOL(vip_configure_genlock);
+EXPORT_SYMBOL(vip_set_genlock_enable);
+EXPORT_SYMBOL(vip_set_power_characteristics);
+EXPORT_SYMBOL(vip_set_priority_characteristics);
+EXPORT_SYMBOL(vip_set_debug_characteristics);
+EXPORT_SYMBOL(vip_configure_pages);
+EXPORT_SYMBOL(vip_set_interrupt_line);
+EXPORT_SYMBOL(vip_reset);
+EXPORT_SYMBOL(vip_set_subwindow_enable);
+EXPORT_SYMBOL(vip_reset_interrupt_state);
+EXPORT_SYMBOL(vip_save_state);
+EXPORT_SYMBOL(vip_restore_state);
+EXPORT_SYMBOL(vip_get_interrupt_state);
+EXPORT_SYMBOL(vip_test_genlock_active);
+EXPORT_SYMBOL(vip_test_signal_status);
+EXPORT_SYMBOL(vip_get_current_field);
+
+#if CIMARRON_INCLUDE_VIP_READ_ROUTINES
+EXPORT_SYMBOL(vip_get_current_mode);
+EXPORT_SYMBOL(vip_get_601_configuration);
+EXPORT_SYMBOL(vip_get_buffer_configuration);
+EXPORT_SYMBOL(vip_get_genlock_configuration);
+EXPORT_SYMBOL(vip_get_genlock_enable);
+EXPORT_SYMBOL(vip_is_buffer_update_latched);
+EXPORT_SYMBOL(vip_get_capture_state);
+EXPORT_SYMBOL(vip_get_current_line);
+EXPORT_SYMBOL(vip_read_fifo);
+EXPORT_SYMBOL(vip_write_fifo);
+EXPORT_SYMBOL(vip_enable_fifo_access);
+EXPORT_SYMBOL(vip_get_power_characteristics);
+EXPORT_SYMBOL(vip_get_priority_characteristics);
+EXPORT_SYMBOL(vip_get_capability_characteristics);
+#endif
+#endif
+
+#if CIMARRON_INCLUDE_VOP
+EXPORT_SYMBOL(vop_set_vbi_window);
+EXPORT_SYMBOL(vop_enable_vbi_output);
+EXPORT_SYMBOL(vop_set_configuration);
+EXPORT_SYMBOL(vop_save_state);
+EXPORT_SYMBOL(vop_restore_state);
+
+#if CIMARRON_INCLUDE_VOP_READ_ROUTINES
+EXPORT_SYMBOL(vop_get_current_mode);
+EXPORT_SYMBOL(vop_get_vbi_configuration);
+EXPORT_SYMBOL(vop_get_vbi_enable);
+EXPORT_SYMBOL(vop_get_crc);
+EXPORT_SYMBOL(vop_read_vbi_crc);
+#endif
+
+#endif
+
+/* export memory api */
+#include "cim_mem.h"
+
+EXPORT_SYMBOL(cim_get_gp_base);
+EXPORT_SYMBOL(cim_get_fb_base);
+EXPORT_SYMBOL(cim_get_fb_size);
+EXPORT_SYMBOL(cim_get_vg_base);
+EXPORT_SYMBOL(cim_get_vid_base);
+EXPORT_SYMBOL(cim_get_vip_base);
+EXPORT_SYMBOL(cim_get_cmd_size);
+EXPORT_SYMBOL(cim_get_cmd_base);
+EXPORT_SYMBOL(cim_get_scr_size);
+EXPORT_SYMBOL(cim_get_fb_active);
+
+EXPORT_SYMBOL(cim_get_gp_ptr);
+EXPORT_SYMBOL(cim_get_fb_ptr);
+EXPORT_SYMBOL(cim_get_vg_ptr);
+EXPORT_SYMBOL(cim_get_vid_ptr);
+EXPORT_SYMBOL(cim_get_vip_ptr);
+EXPORT_SYMBOL(cim_get_cmd_base_ptr);
+EXPORT_SYMBOL(cim_get_cmd_ptr);
+
+
+#ifdef MODULE
+MODULE_AUTHOR("AMD");
+MODULE_DESCRIPTION("Geode GX3 Cimarron graphics engine abstraction layer");
+MODULE_LICENSE("GPL");
+#endif
diff -Nru kernel-2.6.18geode-hurricane.orig/lib/cimarron/cim_dev.c kernel-2.6.18geode-hurricane/lib/cimarron/cim_dev.c
--- kernel-2.6.18geode-hurricane.orig/lib/cimarron/cim_dev.c 1970-01-01 01:00:00.000000000 +0100
+++ kernel-2.6.18geode-hurricane/lib/cimarron/cim_dev.c 2006-12-01 13:21:21.000000000 +0100
@@ -0,0 +1,101 @@
+/*
+ * Copyright (c) 2003-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
+ * */
+/*
+ * */
+/*
+ * Cimarron device driver code
+ * Jordan Crouse (jordan.crouse@amd.com)
+ * */
+
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include "cim_dev.h"
+
+#include "cim/cim_parm.h"
+#include "cim/cim_rtns.h"
+
+static int
+cimdev_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
+ unsigned long arg) {
+
+ switch(cmd) {
+
+ case CIM_RESERVE_MEM: {
+ cim_mem_req_t res;
+ int err;
+
+ if ((err = copy_from_user(&res, (void *) arg, sizeof(res))))
+ return err;
+
+ res.offset = cim_fget_memory(res.owner, res.name, filp,
+ res.size, res.flags);
+
+ return copy_to_user((void *) arg, &res, sizeof(res));
+ }
+
+ case CIM_FREE_MEM: {
+ cim_mem_free_t res;
+ int err;
+
+ if ((err = copy_from_user(&res, (void *) arg, sizeof(res))))
+ return err;
+
+ cim_free_memory(res.owner, res.offset);
+ return 0;
+ }
+ }
+
+ return -EINVAL;
+}
+
+static int
+cimdev_release(struct inode *inode, struct file *filp) {
+ cim_release_memory(filp);
+ return 0;
+}
+
+static struct file_operations cimdev_fops = {
+ owner: THIS_MODULE,
+ release: cimdev_release,
+ ioctl: cimdev_ioctl,
+};
+
+#define CIMDEV_MINOR_DEV 156
+
+static struct miscdevice cimdev_device = {
+ CIMDEV_MINOR_DEV,
+ "cimarron",
+ &cimdev_fops
+};
+
+int cim_init_dev(void) {
+ return misc_register(&cimdev_device);
+}
+
+void cim_exit_dev(void) {
+ misc_deregister(&cimdev_device);
+}
+
diff -Nru kernel-2.6.18geode-hurricane.orig/lib/cimarron/cim_dev.h kernel-2.6.18geode-hurricane/lib/cimarron/cim_dev.h
--- kernel-2.6.18geode-hurricane.orig/lib/cimarron/cim_dev.h 1970-01-01 01:00:00.000000000 +0100
+++ kernel-2.6.18geode-hurricane/lib/cimarron/cim_dev.h 2006-12-01 13:21:21.000000000 +0100
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2003-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
+ * */
+/*
+ * */
+/*
+ * Header file for Linux devicd driver routines for Cimarron
+ * Jordan Crouse (jordan.crouse@amd.com)
+ * */
+
+#ifndef CIMDEV_H_
+#define CIMDEV_H_
+
+#include "cim_mem.h"
+
+#define CIM_RESERVE_MEM 0x01
+#define CIM_FREE_MEM 0x02
+
+typedef struct {
+
+ /* These fields get populated by the client */
+
+ char owner[10];
+ char name[15];
+ int flags;
+ int size;
+
+ /* These fields are populated by the device */
+
+ unsigned long offset;
+} cim_mem_req_t;
+
+typedef struct {
+ char owner[10];
+ unsigned long offset;
+} cim_mem_free_t;
+
+#endif
+
+
diff -Nru kernel-2.6.18geode-hurricane.orig/lib/cimarron/cim_mem.c kernel-2.6.18geode-hurricane/lib/cimarron/cim_mem.c
--- kernel-2.6.18geode-hurricane.orig/lib/cimarron/cim_mem.c 1970-01-01 01:00:00.000000000 +0100
+++ kernel-2.6.18geode-hurricane/lib/cimarron/cim_mem.c 2006-12-01 13:21:21.000000000 +0100
@@ -0,0 +1,414 @@
+/*
+ * Copyright (c) 2003-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
+ * */
+/*
+ * */
+/*
+ * Linux memory management routines for Cimarron
+ * William Morrow (william.morrow@amd.com)
+ * */
+
+#include
+#include
+#include
+#include
+#include
+
+#ifdef CONFIG_PROC_FS
+#include
+#endif
+
+#include "build_num.h"
+
+#include "cim_mem.h"
+#include "cim/cim_parm.h"
+#include "cim/cim_rtns.h"
+
+/* cimarron related data */
+
+unsigned char *cim_get_gp_ptr(void) { return cim_gp_ptr; }
+unsigned char *cim_get_fb_ptr(void) { return cim_fb_ptr; }
+unsigned char *cim_get_vg_ptr(void) { return cim_vg_ptr; }
+unsigned char *cim_get_vid_ptr(void) { return cim_vid_ptr; }
+unsigned char *cim_get_vip_ptr(void) { return cim_vip_ptr; }
+unsigned char *cim_get_cmd_base_ptr(void) { return cim_cmd_base_ptr; }
+unsigned char *cim_get_cmd_ptr(void) { return cim_cmd_ptr; }
+
+/* initalization parameters for above */
+
+unsigned long cim_gp_base = 0;
+unsigned long cim_fb_base = 0;
+unsigned long cim_fb_size = 0;
+unsigned long cim_vg_base = 0;
+unsigned long cim_vid_base = 0;
+unsigned long cim_vip_base = 0;
+unsigned long cim_cmd_size = 0;
+unsigned long cim_cmd_base = 0;
+unsigned long cim_scr_size = 0;
+unsigned long cim_fb_active = 0;
+
+unsigned long cim_get_gp_base(void) { return cim_gp_base; }
+unsigned long cim_get_fb_base(void) { return cim_fb_base; }
+unsigned long cim_get_fb_size(void) { return cim_fb_size; }
+unsigned long cim_get_vg_base(void) { return cim_vg_base; }
+unsigned long cim_get_vid_base(void) { return cim_vid_base; }
+unsigned long cim_get_vip_base(void) { return cim_vip_base; }
+unsigned long cim_get_cmd_size(void) { return cim_cmd_size; }
+unsigned long cim_get_cmd_base(void) { return cim_cmd_base; }
+unsigned long cim_get_scr_size(void) { return cim_scr_size; }
+unsigned long cim_get_fb_active(void) { return cim_fb_active; }
+
+/* Size of the cmd buffer size - this is settable by the module param */
+static int cmdbufsize = 0x200000;
+
+#ifdef MODULE
+MODULE_PARM(cmdbufsize, "i");
+MODULE_PARM_DESC(cmdbufsize, "Size of the GP command buffer (default=2MB)");
+#endif
+
+struct s_cim_mem {
+ struct s_cim_mem *next, *prev; /* Double linked list */
+ unsigned long offset; /* Offset of the block from the FB memory base */
+ unsigned long size; /* Size of the block in bytes */
+ unsigned long flags; /* Flags indicating ownership */
+ struct file *file; /* file owning volatile resource */
+ char name[15]; /* Block identifier */
+ char owner[10]; /* Owner of the block */
+};
+
+static struct s_cim_mem *cim_mem_head = 0;
+static struct s_cim_mem *cim_mem_tail = 0;
+
+static int cim_mem_init = 0; /* initialization done */
+
+#ifdef CONFIG_PROC_FS
+
+static int
+proc_cim_mem_read(char *page, char **start, off_t off, int count,
+ int *eof, void *data)
+{
+ int len = 0;
+ struct s_cim_mem *lp = cim_mem_head;
+
+ while(lp) {
+ len += sprintf(page + len, "%-10s %-15s ",
+ lp->flags & CIM_F_FREE ? "_free_" : lp->owner,
+ lp->flags & CIM_F_FREE ? "_free_" : lp->name);
+
+ len += sprintf(page + len, "0x%02lx 0x%08lx 0x%08lx\n",
+ lp->flags, lp->offset, lp->size);
+
+ lp = lp->next;
+ }
+
+ return len;
+}
+
+#endif
+
+static struct s_cim_mem *
+cim_alloc(const char *owner, const char *name, struct file *file,
+ unsigned long size, int policy, int flags) {
+
+ struct s_cim_mem *ptr =
+ (policy == CIM_ALLOC_BOTTOM) ? cim_mem_head : cim_mem_tail;
+
+ struct s_cim_mem *ret = 0;
+
+ /* Traverse the list looking for a free block */
+ while(ptr) {
+
+ if (!(ptr->flags & CIM_F_FREE) || size > ptr->size) {
+ ptr = (policy == CIM_ALLOC_BOTTOM) ? ptr->next : ptr->prev;
+ continue;
+ }
+
+ if (ptr->size == size) {
+ ret = ptr;
+ }
+ else {
+ ret = kmalloc(sizeof(struct s_cim_mem), GFP_KERNEL);
+ if (!ret) break;
+
+ ret->size = size;
+
+ if (policy == CIM_ALLOC_TOP) {
+ ret->offset = ptr->offset + (ptr->size - size);
+ ret->next = ptr->next;
+ ret->prev = ptr;
+
+ if (ptr->next)
+ ptr->next->prev = ret;
+ else
+ cim_mem_tail = ret;
+
+ ptr->size -= size;
+ ptr->next = ret;
+ }
+ else { /* CIM_ALLOC_BOTTOM */
+ ret->offset = ptr->offset;
+ ret->next = ptr;
+ ret->prev = ptr->prev;
+ if (ptr->prev)
+ ptr->prev->next = ret;
+ else
+ cim_mem_head = ret;
+
+ ptr->offset += size;
+ ptr->size -= size;
+
+ ptr->prev = ret;
+ }
+ }
+
+ break;
+ }
+
+ if (ret) {
+ ret->flags = flags;
+ strncpy(ret->name, name, sizeof(ret->name) - 1);
+ strncpy(ret->owner, owner, sizeof(ret->owner) - 1);
+
+ ret->name[sizeof(ret->name) - 1] = 0;
+ ret->owner[sizeof(ret->owner) - 1] = 0;
+ ret->file = file;
+ }
+
+ return ret;
+}
+
+static void cim_free(struct s_cim_mem *block) {
+
+ struct s_cim_mem *ret = block;
+ struct s_cim_mem *prev, *next;
+
+ prev = block->prev;
+
+ /* Check to see if we can merge the previous block */
+
+ if (prev && prev->flags & CIM_F_FREE) {
+ ret = prev;
+ ret->size += block->size;
+ ret->next = block->next;
+
+ if (block->next) block->next->prev = ret;
+ else cim_mem_tail = ret;
+
+ kfree(block);
+ }
+
+ next = ret->next;
+
+ /* Merge the next block in, if we can */
+
+ if (next && next->flags & CIM_F_FREE) {
+ ret->size += next->size;
+ ret->next = next->next;
+
+ if (next->next) next->next->prev = ret;
+ else cim_mem_tail = ret;
+
+ kfree(next);
+ }
+
+ ret->flags = CIM_F_FREE;
+
+ ret->name[0] = 0;
+ ret->owner[0] = 0;
+ ret->file = 0;
+}
+
+int
+cim_init_memory(void)
+{
+ unsigned long cpu_version = 0, companion = 0;
+ struct proc_dir_entry *procdir = 0;
+ INIT_BASE_ADDRESSES cim_base_addr;
+
+ if( cim_mem_init != 0 ) return 0; /* Already set up */
+
+ /* Allocate the inital free block */
+ cim_mem_head = cim_mem_tail = kmalloc(sizeof(struct s_cim_mem), GFP_KERNEL);
+ if (!cim_mem_head)
+ return -ENOMEM;
+
+ if( init_detect_cpu(&cpu_version, &companion) != CIM_STATUS_OK )
+ return -ENODEV;
+
+ init_read_base_addresses(&cim_base_addr);
+
+ /* publicize the init phys addresses used for virtual mappings */
+ cim_gp_base = cim_base_addr.gp_register_base;
+ cim_fb_base = cim_base_addr.framebuffer_base;
+ cim_fb_size = cim_base_addr.framebuffer_size;
+ cim_vg_base = cim_base_addr.vg_register_base;
+ cim_vid_base = cim_base_addr.df_register_base;
+ cim_vip_base = cim_base_addr.vip_register_base;
+ cim_cmd_size = cmdbufsize;
+ cim_scr_size = CIM_SCRATCH_SIZE;
+ cim_fb_active = cim_fb_size - cim_cmd_size - cim_scr_size;
+
+ /* initialize cimarron */
+ cim_gp_ptr = (unsigned char *)ioremap(cim_gp_base,0x4000);
+ cim_fb_ptr = (unsigned char *)ioremap(cim_fb_base,cim_fb_size);
+ cim_vg_ptr = (unsigned char *)ioremap(cim_vg_base,0x4000);
+ cim_vid_ptr = (unsigned char *)ioremap(cim_vid_base,0x4000);
+ cim_vip_ptr = (unsigned char *)ioremap(cim_vip_base,0x4000);
+
+ if( !cim_gp_ptr || !cim_fb_ptr || !cim_vg_ptr ||
+ !cim_vid_ptr || !cim_vip_ptr ) return -ENODEV;
+
+ gp_set_frame_buffer_base(cim_fb_base,cim_fb_size-cim_cmd_size);
+ cim_cmd_base_ptr = cim_fb_ptr + cim_fb_size - cim_cmd_size;
+ cim_cmd_base = cim_fb_base + cim_fb_size - cim_cmd_size;
+ gp_set_command_buffer_base(cim_cmd_base,0,cim_cmd_size);
+
+ /* Initalize the heap memory */
+
+ cim_mem_head->next = cim_mem_head->prev = NULL;
+
+ cim_mem_head->offset = cim_base_addr.framebuffer_base;
+ cim_mem_head->size = cim_base_addr.framebuffer_size;
+ cim_mem_head->name[0] = 0;
+ cim_mem_head->owner[0] = 0;
+ cim_mem_head->file = 0;
+
+ cim_mem_head->flags = CIM_F_FREE; /* Mark the whole block as free */
+
+ /* Now, allocate the space for the GP block */
+ cim_alloc("cimarron", "gp_cmd_buffer", 0, cim_cmd_size,
+ CIM_ALLOC_TOP, CIM_F_CMDBUF);
+ cim_alloc("cimarron", "gp_scr_buffer", 0, cim_scr_size,
+ CIM_ALLOC_TOP, CIM_F_PRIVATE);
+
+#ifdef CONFIG_PROC_FS
+ procdir = proc_mkdir("driver/cimarron", 0);
+ create_proc_read_entry ("map", 0, procdir, proc_cim_mem_read, NULL);
+#endif
+
+ cim_mem_init = 1;
+ return 0;
+}
+
+unsigned long
+cim_fget_memory(char *owner, char *entity, struct file *file, int size, int flags)
+{
+ struct s_cim_mem *lp;
+ int policy;
+
+ /* Policy is 0 if it should come from the top, or 1 if it should
+ come from the bottom of memory */
+
+ /* Public memory space should be allocated from the bottom, anything
+ else from the top */
+
+ policy = (flags & CIM_F_PUBLIC) ? CIM_ALLOC_BOTTOM : CIM_ALLOC_TOP;
+
+ if (size <= 0) return 0;
+
+ for(lp = cim_mem_head; lp; lp = lp->next) {
+ if (!strcmp(lp->owner, owner) && !strcmp(lp->name, entity))
+ break;
+ }
+
+ if (!lp) {
+ if (!(lp = cim_alloc(owner, entity, file, size, policy, flags)))
+ return 0;
+ }
+
+ return lp->offset;
+}
+
+unsigned long
+cim_get_memory(char *owner, char *entity, int size, int flags)
+{
+ return cim_fget_memory(owner,entity,0,size,flags);
+}
+
+unsigned long
+cim_find_memory(cim_mem_find_t *find, int *size) {
+ struct s_cim_mem *lp = 0;
+
+ if (!find)
+ return *size=0;
+
+ for( lp = cim_mem_head; lp; lp = lp->next) {
+
+ if (find->match & CIM_MATCH_OWNER)
+ if (!lp->owner || strcmp(lp->owner, find->owner)) continue;
+
+ if (find->match & CIM_MATCH_NAME)
+ if (!lp->name || strcmp(lp->name, find->name)) continue;
+
+ if (find->match & CIM_MATCH_FLAGS)
+ if (!(lp->flags & find->flags)) continue;
+
+ break;
+ }
+
+ if (size)
+ *size = lp ? lp->size : 0;
+
+ return lp ? lp->offset : 0;
+}
+
+void
+cim_free_memory(char *owner, unsigned long offset)
+{
+ struct s_cim_mem *lp;
+
+ for(lp = cim_mem_head; lp; lp = lp->next) {
+ if (lp->offset == offset && !strcmp(lp->owner, owner)) {
+ cim_free(lp);
+ return;
+ }
+ }
+}
+
+void
+cim_release_memory(struct file *file)
+{
+ struct s_cim_mem *lp;
+ for(;;) {
+ for( lp=cim_mem_head; lp!=NULL && lp->file!=file; lp=lp->next );
+ if( lp == NULL ) break;
+ cim_free(lp);
+ }
+}
+
+void
+cim_exit_memory(void)
+{
+ struct s_cim_mem *lp = cim_mem_head, *np = 0;
+
+#ifdef CONFIG_PROC_FS
+ remove_proc_entry ("driver/cimarron", NULL);
+#endif
+
+ for( ; lp!=NULL; lp=np ) kfree((np=lp->next, lp));
+
+ cim_mem_head = cim_mem_tail = 0;
+ cim_mem_init = 0;
+}
+
+EXPORT_SYMBOL(cim_get_memory);
+EXPORT_SYMBOL(cim_free_memory);
+EXPORT_SYMBOL(cim_find_memory);
+
diff -Nru kernel-2.6.18geode-hurricane.orig/lib/cimarron/cim_mem.h kernel-2.6.18geode-hurricane/lib/cimarron/cim_mem.h
--- kernel-2.6.18geode-hurricane.orig/lib/cimarron/cim_mem.h 1970-01-01 01:00:00.000000000 +0100
+++ kernel-2.6.18geode-hurricane/lib/cimarron/cim_mem.h 2006-12-01 13:21:21.000000000 +0100
@@ -0,0 +1,87 @@
+/*
+ * Copyright (c) 2003-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
+ * */
+/*
+ * */
+/*
+ * Header file for Linux memory management routines for Cimarron
+ * Jordan Crouse (jordan.crouse@amd.com)
+ * */
+
+#ifndef CIMMEM_H_
+#define CIMMEM_H_
+
+#define CIM_SCRATCH_SIZE 0x100000
+
+/* Allocation schemes */
+
+#define CIM_ALLOC_TOP 0
+#define CIM_ALLOC_BOTTOM 1
+
+/* Block flags */
+#define CIM_F_FREE 0x01 /* This block is marked as free */
+#define CIM_F_CMDBUF 0x02 /* GP command buffer flag */
+#define CIM_F_PRIVATE 0x04 /* This block is reserved only for its owner */
+#define CIM_F_PUBLIC 0x08 /* This block can be used by the world, not just */
+ /* the owner */
+
+#ifdef __KERNEL__
+#include
+
+typedef struct {
+ int match;
+ char name[15];
+ char owner[10];
+ int flags;
+} cim_mem_find_t;
+
+#define CIM_MATCH_OWNER 0x1
+#define CIM_MATCH_NAME 0x2
+#define CIM_MATCH_FLAGS 0x4
+
+int cim_init_memory(void);
+unsigned long cim_get_memory(char *, char *, int, int);
+unsigned long cim_fget_memory(char *, char *, struct file *, int, int);
+unsigned long cim_find_memory(cim_mem_find_t *, int *);
+
+void cim_free_memory(char *, unsigned long);
+void cim_release_memory(struct file *);
+
+unsigned long cim_get_gp_base(void);
+unsigned long cim_get_fb_base(void);
+unsigned long cim_get_fb_size(void);
+unsigned long cim_get_vg_base(void);
+unsigned long cim_get_vid_base(void);
+unsigned long cim_get_vip_base(void);
+unsigned long cim_get_cmd_size(void);
+unsigned long cim_get_cmd_base(void);
+unsigned long cim_get_scr_size(void);
+unsigned long cim_get_fb_active(void);
+
+unsigned char *cim_get_gp_ptr(void);
+unsigned char *cim_get_fb_ptr(void);
+unsigned char *cim_get_vg_ptr(void);
+unsigned char *cim_get_vid_ptr(void);
+unsigned char *cim_get_vip_ptr(void);
+unsigned char *cim_get_cmd_base_ptr(void);
+unsigned char *cim_get_cmd_ptr(void);
+
+#endif
+#endif
diff -Nru kernel-2.6.18geode-hurricane.orig/lib/cimarron/cim_mod.c kernel-2.6.18geode-hurricane/lib/cimarron/cim_mod.c
--- kernel-2.6.18geode-hurricane.orig/lib/cimarron/cim_mod.c 1970-01-01 01:00:00.000000000 +0100
+++ kernel-2.6.18geode-hurricane/lib/cimarron/cim_mod.c 2006-12-01 13:21:21.000000000 +0100
@@ -0,0 +1,123 @@
+/*
+ * Copyright (c) 2003-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
+ * */
+/*
+ * */
+/*
+ * Cimarron module initalization
+ * Jordan Crouse (jordan.crouse@amd.com)
+ * */
+
+#include
+#include
+#include
+#include
+#include
+
+#include "cim_mem.h"
+#include "cim_dev.h"
+#include "build_num.h"
+
+#ifdef MODULE
+MODULE_AUTHOR("Advanced Micro Devices, Inc.");
+MODULE_DESCRIPTION("AMD Geode LX Graphics Abstraction Layer");
+MODULE_LICENSE("GPL");
+#endif
+
+#define CIM_MOD_DRIVER_NAME "cimarron"
+
+int cim_init_dev(void);
+void cim_exit_dev(void);
+
+int cim_init_memory(void);
+void cim_exit_memory(void);
+/* We do this because there really isn't any way to verify that the
+ KFB or V4L2 is going to be loaded before Cimarron is. We force
+ the issue by asking the other entities to call cim_mod_init()
+ and we set a flag indicating that we have already been set up
+*/
+
+static int cim_init_flag = 0;
+
+static int
+cim_mod_probe(struct pci_dev *pcidev, const struct pci_device_id *pciid) {
+ int ret;
+ ret = pci_enable_device(pcidev);
+ if (ret) return ret;
+ ret = cim_init_memory();
+ if (ret) return ret;
+
+ ret = cim_init_dev();
+ if (ret) {
+ cim_exit_memory();
+ return ret;
+ }
+ return 0;
+}
+
+static void
+cim_mod_remove(struct pci_dev *dev) {
+ cim_exit_memory();
+ cim_exit_dev();
+}
+
+static struct
+pci_device_id cim_mod_id_table[] __devinitdata = {
+ {PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_LX_VIDEO, \
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ {0,}
+};
+
+MODULE_DEVICE_TABLE(pci, cim_mod_id_table);
+
+static struct
+pci_driver cim_mod_driver = {
+ name: CIM_MOD_DRIVER_NAME,
+ id_table: cim_mod_id_table,
+ probe: cim_mod_probe,
+ remove: cim_mod_remove
+};
+
+int __init
+cim_mod_init(void)
+{
+ int ret;
+ if( cim_init_flag != 0 ) return 0;
+ printk(KERN_INFO "%s\n", AMD_VERSION);
+ ret = pci_module_init(&cim_mod_driver);
+ if( ret == 0 ) cim_init_flag = 1;
+ return ret;
+}
+
+#ifdef MODULE
+void __exit
+cim_mod_exit(void)
+{
+ printk(KERN_INFO CIM_MOD_DRIVER_NAME " unloading\n");
+ pci_unregister_driver(&cim_mod_driver);
+ cim_init_flag = 0;
+}
+#endif
+
+module_init(cim_mod_init);
+
+#ifdef MODULE
+module_exit(cim_mod_exit);
+#endif
diff -Nru kernel-2.6.18geode-hurricane.orig/lib/cimarron/Makefile kernel-2.6.18geode-hurricane/lib/cimarron/Makefile
--- kernel-2.6.18geode-hurricane.orig/lib/cimarron/Makefile 1970-01-01 01:00:00.000000000 +0100
+++ kernel-2.6.18geode-hurricane/lib/cimarron/Makefile 2006-12-01 13:21:21.000000000 +0100
@@ -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 -Nru kernel-2.6.18geode-hurricane.orig/lib/Kconfig kernel-2.6.18geode-hurricane/lib/Kconfig
--- kernel-2.6.18geode-hurricane.orig/lib/Kconfig 2006-12-01 10:28:25.000000000 +0100
+++ kernel-2.6.18geode-hurricane/lib/Kconfig 2006-12-01 10:33:07.000000000 +0100
@@ -46,6 +46,15 @@
config DYN_PAGEFLAGS
bool
+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 -Nru kernel-2.6.18geode-hurricane.orig/lib/Makefile kernel-2.6.18geode-hurricane/lib/Makefile
--- kernel-2.6.18geode-hurricane.orig/lib/Makefile 2006-12-01 10:28:25.000000000 +0100
+++ kernel-2.6.18geode-hurricane/lib/Makefile 2006-12-01 10:33:07.000000000 +0100
@@ -45,6 +45,7 @@
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