--- a/drivers/video/Kconfig
+++ b/drivers/video/Kconfig
@@ -255,6 +255,25 @@ config FB_CIRRUS
 	  Say N unless you have such a graphics board or plan to get one
 	  before you next recompile the kernel.
 
+config FB_EP93XX
+	tristate "EP93xx frame buffer support"
+	depends on FB
+	select FB_CFB_FILLRECT
+	select FB_CFB_COPYAREA
+	select FB_CFB_IMAGEBLIT
+	help
+	  This is the frame buffer device driver for the internal raster engine
+	  on certain members of the EP93xx family.  For VGA and LCD output.
+
+config FB_EP93XX_MONO
+	tristate "EP93xx Mono frame buffer support"
+	depends on FB
+	select FB_CFB_FILLRECT
+	select FB_CFB_COPYAREA
+	help
+	  This is the frame buffer device driver for the internal raster engine
+	  on certain members of the EP93xx family. For LCD output.
+
 config FB_PM2
 	tristate "Permedia2 support"
 	depends on FB && ((AMIGA && BROKEN) || PCI)
--- a/drivers/video/Makefile
+++ b/drivers/video/Makefile
@@ -95,6 +95,8 @@ obj-$(CONFIG_FB_ARMCLCD)	  += amba-clcd.
 obj-$(CONFIG_FB_68328)            += 68328fb.o
 obj-$(CONFIG_FB_GBE)              += gbefb.o
 obj-$(CONFIG_FB_CIRRUS)		  += cirrusfb.o
+obj-$(CONFIG_FB_EP93XX)		  += ep93xxfb.o
+obj-$(CONFIG_FB_EP93XX_MONO)	  += ep93xxfb_mono.o
 obj-$(CONFIG_FB_ASILIANT)	  += asiliantfb.o
 obj-$(CONFIG_FB_PXA)		  += pxafb.o
 obj-$(CONFIG_FB_W100)		  += w100fb.o
--- /dev/null
+++ b/drivers/video/ep93xxfb.c
@@ -0,0 +1,1628 @@
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/reboot.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/delay.h>
+#include <linux/fb.h>
+#include <linux/init.h>
+#include <linux/ioport.h>
+#include <linux/interrupt.h>
+#include <linux/dma-mapping.h>
+#include <asm/io.h>
+#include <asm/uaccess.h>
+#include "ep93xxfb.h"
+#include <mach/hardware.h>
+#include <linux/platform_device.h>
+
+#include "console/fbcon.h"
+
+
+#if defined(CONFIG_MACH_EDB9312) || defined(CONFIG_MACH_EDB9315) || defined(CONFIG_MACH_EDB9307) || defined(CONFIG_MACH_EDB9301) || defined(CONFIG_MACH_EDB9302)
+#define CONFIG_EP93XX_SDCS3
+#else
+#define CONFIG_EP93XX_SDCS0
+#endif
+
+//#define DEBUG 1
+#ifdef DEBUG
+#define DPRINTK( fmt, arg... )  printk( fmt, ##arg )
+#else
+#define DPRINTK( fmt, arg... )
+#endif
+
+#define FBDEV_NAME "ep93xxfb"
+
+#define ep93xxfb_outl(value, reg)              \
+{                                              \
+    outl(RASTER_SWLOCK_VALUE, RASTER_SWLOCK);  \
+    outl(value, reg);                          \
+}
+
+#define DEFAULT_OUT   CRT_OUT
+#define DEFAULT_MODE	7
+#define DEFAULT_BPP 	24
+
+static DECLARE_WAIT_QUEUE_HEAD(ep93xxfb_wait_in);
+
+static unsigned int pseudo_palette[256];
+static unsigned long *cursor_data = NULL;
+static struct ep93xxfb_info epinfo;
+
+static int vout =  DEFAULT_OUT;
+static int vmode = DEFAULT_MODE;
+static int depth = DEFAULT_BPP;
+
+
+static int ep93xxfb_setcol(struct fb_info *info, int bpp);
+
+
+static struct ep93xxfb_videomodes ep93xxfb_vmods[] = {
+    {
+	"Philips-LB064V02-640x480x60",
+        640, 24, 96, 40, 480, 10, 2, 33, 60,
+        CLK_INTERNAL, EDGE_FALLING, POL_LOW, POL_LOW, POL_LOW,
+    },
+    { // 1
+        "CRT-640x480-60",
+        640, 24, 96, 40, 480, 11, 2, 32, 60,
+        CLK_INTERNAL, EDGE_RISING, POL_LOW, POL_LOW, POL_LOW,
+    },
+    { // 2
+        "CRT-640x480-72",
+        640, 40, 40, 144, 480, 8, 3, 30, 72,
+        CLK_INTERNAL, EDGE_RISING, POL_LOW, POL_LOW, POL_LOW,
+    },
+    { // 3
+        "CRT-640x480-75",
+	640, 16, 76, 120, 480, 1, 3, 16, 75,
+        CLK_INTERNAL, EDGE_RISING, POL_LOW, POL_LOW, POL_LOW,
+    },
+    { // 4
+	"CRT-640x480-85",
+	640, 56, 56, 80, 480, 1, 3, 25, 85,
+	CLK_INTERNAL, EDGE_RISING, POL_LOW, POL_LOW, POL_LOW,
+    },
+    { // 5
+	"CTR-640x480-100",
+	640, 32, 96, 96, 480, 8, 6, 36, 100,
+        CLK_INTERNAL, EDGE_RISING, POL_LOW, POL_LOW, POL_LOW,
+    },
+    { // 6
+	"CRT-800x600-56",
+	800, 24, 72, 128, 600, 1, 2, 22, 56,
+        CLK_INTERNAL, EDGE_RISING, POL_LOW, POL_LOW, POL_LOW,
+    },
+    { // 7
+        "CRT-800x600-60",
+        800, 40, 128, 88, 600, 1, 4, 23, 60,
+        CLK_INTERNAL, EDGE_RISING, POL_LOW, POL_HIGH, POL_HIGH,
+    },
+    { // 8
+	"CRT-800x600-72",
+	800, 56, 120, 64, 600, 37, 6, 23, 72,
+        CLK_INTERNAL, EDGE_RISING, POL_LOW, POL_LOW, POL_LOW,
+    },
+    { // 9
+	"CRT-800x600-85",
+	800, 64, 64, 160, 600, 16, 5, 36, 85,
+        CLK_INTERNAL, EDGE_RISING, POL_LOW, POL_LOW, POL_LOW,
+    },
+    { // 10
+        "CRT-800x600-100",
+	800, 64, 64, 160, 600, 4, 6, 30, 100,
+	CLK_INTERNAL, EDGE_RISING, POL_LOW, POL_LOW, POL_LOW,
+    },
+    { // 11
+        "CRT-1024x768-60",
+	1024, 8, 144, 168, 768, 3, 6, 29, 60,
+	CLK_INTERNAL, EDGE_RISING, POL_LOW, POL_LOW, POL_LOW,
+    },
+    { // 12
+	"CRT-1024x768-70",
+	1024, 24, 136, 144, 768, 3, 6, 29, 70,
+        CLK_INTERNAL, EDGE_RISING, POL_LOW, POL_LOW, POL_LOW,
+    },
+    { // 13
+	"CRT-1024x768-75",
+	1024, 16, 96, 176, 768, 1, 3, 28, 75,
+	CLK_INTERNAL, EDGE_RISING, POL_LOW, POL_HIGH, POL_HIGH,
+    },
+    { // 14
+	"CRT-1024x768-85",
+	1024, 48, 96, 208, 768, 1, 3, 36, 85,
+	CLK_INTERNAL, EDGE_RISING, POL_LOW, POL_HIGH, POL_HIGH,
+    },
+    { // 15
+        "CRT-1280x720-60",
+	1280, 48, 112, 248, 720, 1, 3, 38, 60,
+        CLK_INTERNAL, EDGE_RISING, POL_LOW, POL_HIGH, POL_HIGH,
+    }
+};
+
+static void philips_lb064v02_on(unsigned char value)
+{
+    DPRINTK("philips_lb064v02_on \n");
+    outl(inl(GPIO_PADDR) | 2, GPIO_PADDR);
+    outl(inl(GPIO_PADR) | 2, GPIO_PADR);
+}
+
+static void philips_lb064v02_off(unsigned char value)
+{
+    DPRINTK("philips_lb064v02_off \n");
+    outl(inl(GPIO_PADR) & ~2, GPIO_PADR);
+}
+
+static irqreturn_t ep93xxfb_irq_handler(int i, void *blah)
+{
+    outl(0x00000000, BLOCKCTRL);
+    wake_up(&ep93xxfb_wait_in);
+    return IRQ_HANDLED;
+}
+
+static void ep93xxfb_wait(void)
+{
+    DECLARE_WAITQUEUE(wait, current);
+    add_wait_queue(&ep93xxfb_wait_in, &wait);
+    set_current_state(TASK_UNINTERRUPTIBLE);
+
+    while (inl(BLOCKCTRL) & 0x00000001){
+	if(/*(pls_proba==1)&&*/(!in_atomic()))
+	    schedule();
+    }
+
+    remove_wait_queue(&ep93xxfb_wait_in, &wait);
+    set_current_state(TASK_RUNNING);
+
+}
+
+void ep93xxfb_fillrect(struct fb_info *p, const struct fb_fillrect *fill)
+{
+    unsigned long blkdestwidth,tmp;
+
+    if (!fill->width || !fill->height ||
+	(fill->dx >= p->var.xres) ||
+	(fill->dy >= p->var.yres) ||
+        ((fill->dx + fill->width - 1) >= p->var.xres) ||
+        ((fill->dy + fill->height - 1) >= p->var.yres))
+        return;
+
+    tmp =  (( fill->dx + fill->width ) * epinfo.bpp );
+    blkdestwidth = tmp / 32;
+    if(blkdestwidth > 0 && (tmp % 32 == 0))
+	blkdestwidth--;
+    blkdestwidth = blkdestwidth - (fill->dx * epinfo.bpp) / 32;
+
+    outl(fill->color, BLOCKMASK);
+    outl( ((fill->dx * epinfo.bpp) & 0x1F) |
+	  ((((fill->dx + fill->width - 1) * epinfo.bpp ) & 0x1F) << 16),
+	  DESTPIXELSTRT);
+    outl( ((epinfo.xres * epinfo.bpp) / 32), DESTLINELENGTH);
+    outl( blkdestwidth, BLKDESTWIDTH );
+    outl(fill->height - 1, BLKDESTHEIGHT);
+    outl((epinfo.fb_phys + (fill->dy * epinfo.xres * epinfo.bpp ) / 8 +
+	 (fill->dx * epinfo.bpp ) / 8 )
+	 , BLKDSTSTRT);
+    outl( epinfo.pixformat | 0x0000000B, BLOCKCTRL);
+    ep93xxfb_wait();
+
+}
+
+void ep93xxfb_copyarea(struct fb_info *p, const struct fb_copyarea *area)
+{
+    unsigned long startsx,stopsx,startdx,stopdx,startsy,startdy;
+    unsigned long blksrcwidth,blkdestwidth,tmp;
+    unsigned long val = 0;
+
+    if( !area->width || !area->width ||
+	(area->sx >= p->var.xres) || (area->sy >= p->var.yres) ||
+        (area->dx >= p->var.xres) || (area->dy >= p->var.yres) ||
+        ((area->dx + area->width - 1) >= p->var.xres) ||
+        ((area->dy + area->height - 1) >= p->var.yres))
+	return;
+
+    if(area->sx == area->dx && area->sy == area->dy)
+	return;
+
+    if ((area->dy == area->sy) && (area->dx > area->sx) &&
+	(area->dx < (area->sx + area->width - 1))) {
+	startdx = area->dx + area->width - 1;
+        stopdx = area->dx;
+        startsx = area->sx + area->width - 1;
+        stopsx = area->sx;
+        val |= 0x000000A0;
+    }
+    else {
+	startdx = area->dx;
+        stopdx = area->dx + area->width - 1;
+        startsx = area->sx;
+        stopsx = area->sx + area->width - 1;
+    }
+
+    if (area->dy <= area->sy) {
+        startdy = area->dy;
+        startsy = area->sy;
+    }
+    else {
+	startdy = area->dy + area->height -1;
+	startsy = area->sy + area->height -1;
+	val |= 0x00000140;
+    }
+
+    tmp =  (( area->sx + area->width ) * epinfo.bpp );
+    blksrcwidth = tmp / 32;
+    if(blksrcwidth > 0 && (tmp % 32 == 0))
+	blksrcwidth--;
+    blksrcwidth = blksrcwidth - (area->sx * epinfo.bpp) / 32;
+
+    tmp =  (( area->dx + area->width ) * epinfo.bpp );
+    blkdestwidth = tmp / 32;
+    if(blkdestwidth > 0 && (tmp % 32 == 0))
+        blkdestwidth--;
+    blkdestwidth = blkdestwidth - (area->dx * epinfo.bpp) / 32;
+
+    outl( 0x00000000 , BLOCKCTRL);
+
+    /*** src ***/
+    outl((((startsx * epinfo.bpp) & 0x1F) |
+         (((stopsx * epinfo.bpp ) & 0x1F) << 16))
+	 , SRCPIXELSTRT);
+    outl((epinfo.fb_phys + (startsy * epinfo.xres * epinfo.bpp ) / 8 +
+         (startsx * epinfo.bpp ) / 8 )
+	 , BLKSRCSTRT);
+    outl(((epinfo.xres * epinfo.bpp) / 32), SRCLINELENGTH);
+    outl( blksrcwidth, BLKSRCWIDTH );
+
+    /*** dest ***/
+    outl((((startdx * epinfo.bpp) & 0x1F) |
+	 (((stopdx * epinfo.bpp ) & 0x1F) << 16))
+	 , DESTPIXELSTRT);
+    outl((epinfo.fb_phys + (startdy * epinfo.xres * epinfo.bpp ) / 8 +
+         (startdx * epinfo.bpp ) / 8 )
+	 , BLKDSTSTRT);
+    outl( ((epinfo.xres * epinfo.bpp) / 32), DESTLINELENGTH);
+    outl( blkdestwidth, BLKDESTWIDTH);
+    outl( area->height - 1 , BLKDESTHEIGHT);
+    outl( epinfo.pixformat | val | 0x00000003, BLOCKCTRL);
+    ep93xxfb_wait();
+}
+
+void ep93xxfb_imageblit(struct fb_info *p, const struct fb_image *image)
+{
+//    unsigned long blkdestwidth,tmp;
+//    void * pucBlitBuf;
+    cfb_imageblit( p , image );
+    return;
+/*
+    if ((image->dx >= p->var.xres) ||
+        (image->dy >= p->var.yres) ||
+        ((image->dx + image->width - 1) >= p->var.xres) ||
+        ((image->dy + image->height - 1) >= p->var.yres))
+        return;
+    if (epinfo.bpp != image->depth )
+	return;
+
+    tmp =  (( image->dx + image->width ) * epinfo.bpp );
+    blkdestwidth = tmp / 32;
+    if(blkdestwidth > 0 && (tmp % 32 == 0))
+	blkdestwidth--;
+    blkdestwidth = blkdestwidth - (image->dx * epinfo.bpp) / 32;
+
+    pucBlitBuf = kmalloc(1024*8,GFP_KERNEL);
+    copy_from_user(pucBlitBuf, image->data, 5000);
+
+    outl( 0x00000000 , BLOCKCTRL);
+
+    outl( 0x00000000, SRCPIXELSTRT);
+    outl( virt_to_phys(pucBlitBuf), BLKSRCSTRT);
+    outl( (image->width * epinfo.bpp) / 32 , SRCLINELENGTH);
+    outl(((image->width - 1) * epinfo.bpp) / 32, BLKSRCWIDTH );
+
+    outl(((image->dx * epinfo.bpp) & 0x1F) |
+         ((((image->dx + image->width - 1) * epinfo.bpp ) & 0x1F) << 16)
+         , DESTPIXELSTRT);
+    outl((epinfo.fb_phys + (image->dy * epinfo.xres * epinfo.bpp ) / 8 +
+         (image->dx * epinfo.bpp ) / 8 )
+         , BLKDSTSTRT);
+    outl( ((epinfo.xres * epinfo.bpp) / 32), DESTLINELENGTH );
+    outl( blkdestwidth, BLKDESTWIDTH );
+    outl( image->height - 1 , BLKDESTHEIGHT);
+    outl(image->fg_color, BLOCKMASK);
+    outl(image->bg_color, BACKGROUND);
+    outl( epinfo.pixformat | 0x00000003, BLOCKCTRL );
+    ep93xxfb_wait();
+*/
+}
+
+
+static unsigned long isqrt(unsigned long a)
+{
+    unsigned long rem = 0;
+    unsigned long root = 0;
+    int i;
+
+    for (i = 0; i < 16; i++) {
+        root <<= 1;
+        rem = ((rem << 2) + (a >> 30));
+        a <<= 2;
+        root++;
+        if (root <= rem) {
+            rem -= root;
+            root++;
+        }
+	else
+            root--;
+    }
+    return root >> 1;
+}
+
+int ep93xxfb_line(struct fb_info *info,  struct ep93xx_line *line)
+{
+    unsigned long value = 0;
+    long x, y, dx, dy, count, xinc, yinc, xval, yval, incr;
+
+    if ((line->x1 > info->var.xres) ||
+        (line->x2 > info->var.xres) ||
+        (line->y1 > info->var.yres) ||
+        (line->y2 > info->var.yres))
+	return -EFAULT;
+    x = line->x1;
+    y = line->y1;
+    dx = line->x2 - line->x1;
+    dy = line->y2 - line->y1;
+
+    if ( !dx || !dy )
+    	return -EFAULT;
+
+    if ( dx < 0 && dy < 0 ) {
+	x = line->x2;
+	y = line->y2;
+	dx *= -1;
+	dy *= -1;
+    }
+    else if ( dx < 0 && dy > 0 ){
+        dx *= -1;
+	value = 0x000000A0;
+    }
+    else if( dy < 0 && dx > 0 ){
+	dy *= -1;
+        value = 0x00000140;
+    }
+
+    if (line->flags & LINE_PRECISE) {
+	count = isqrt(((dy * dy) + (dx * dx)) * 4096);
+	xinc = (4095 * 64 * dx) / count;
+	yinc = (4095 * 64 * dy) / count;
+	xval = 2048;
+	yval = 2048;
+	count = 0;
+	while (dx || dy) {
+	    incr = 0;
+	    xval -= xinc;
+	    if (xval <= 0) {
+		xval += 4096;
+		dx--;
+		incr = 1;
+	    }
+	    yval -= yinc;
+	    if (yval <= 0) {
+		yval += 4096;
+		dy--;
+		incr = 1;
+	    }
+	    count += incr;
+	}
+    }
+    else {
+        if ( dx == dy ) {
+            xinc = 4095;
+            yinc = 4095;
+            count = dx;
+
+        }
+	else if ( dx < dy ) {
+            xinc = ( dx * 4095 ) / dy;
+            yinc = 4095;
+	    count = dy;
+
+	}
+	else {
+            xinc = 4095;
+            yinc = ( dy * 4095 ) / dx;
+            count = dx;
+        }
+    }
+
+    outl(0x08000800, LINEINIT);
+    if (line->flags & LINE_PATTERN)
+        outl(line->pattern, LINEPATTRN);
+    else
+        outl(0x000fffff, LINEPATTRN);
+    outl(epinfo.fb_phys + ((y * epinfo.xres * epinfo.bpp) / 8) +
+         ((x * epinfo.bpp ) / 8 ), BLKDSTSTRT);
+
+    outl(((x * epinfo.bpp) & 0x1F) |
+         ((((x + dx - 1) * epinfo.bpp) & 0x1F ) << 16),
+	  DESTPIXELSTRT);
+    outl((epinfo.xres * epinfo.bpp) / 32, DESTLINELENGTH);
+    outl(line->fgcolor, BLOCKMASK);
+    outl(line->bgcolor, BACKGROUND);
+    outl((yinc << 16) | xinc, LINEINC);
+    outl( count & 0xFFF, BLKDESTWIDTH);
+    outl( 0  , BLKDESTHEIGHT);
+    value |= (line->flags & LINE_BACKGROUND) ? 0x00004000 : 0;
+    outl(epinfo.pixformat | value | 0x00000013, BLOCKCTRL);
+    ep93xxfb_wait();
+    return 0;
+}
+
+int ioctl_cursor=0;
+
+int ep93xxfb_cursor(struct fb_info *info, struct ep93xx_cursor *cursor)
+{
+    unsigned long x,y,save;
+
+    if((cursor->width ==0)  || (cursor->height ==0) )
+    {
+	struct fb_cursor *fbcon_cursor =(struct fb_cursor *)cursor;
+	struct fbcon_ops *ops = (struct fbcon_ops *)info->fbcon_par;
+	unsigned int scan_align = info->pixmap.scan_align - 1;
+	unsigned int buf_align = info->pixmap.buf_align - 1;
+	unsigned int i, size, dsize, s_pitch, d_pitch;
+	struct fb_image *image;
+	u8 *src, *dst;
+
+	if(ioctl_cursor==1 ){
+		DPRINTK("softcursor error return\n");
+		return 0;
+	}
+
+
+        if (info->state != FBINFO_STATE_RUNNING)
+                return 0;
+
+        s_pitch = (fbcon_cursor->image.width + 7) >> 3;
+        dsize = s_pitch * fbcon_cursor->image.height;
+
+        if (dsize + sizeof(struct fb_image) != ops->cursor_size) {
+                if (ops->cursor_src != NULL)
+                        kfree(ops->cursor_src);
+                ops->cursor_size = dsize + sizeof(struct fb_image);
+
+                ops->cursor_src = kmalloc(ops->cursor_size, GFP_ATOMIC);
+                if (!ops->cursor_src) {
+                        ops->cursor_size = 0;
+                        return -ENOMEM;
+                }
+        }
+        src = ops->cursor_src + sizeof(struct fb_image);
+        image = (struct fb_image *)ops->cursor_src;
+        *image = fbcon_cursor->image;
+        d_pitch = (s_pitch + scan_align) & ~scan_align;
+
+        size = d_pitch * image->height + buf_align;
+        size &= ~buf_align;
+        dst = fb_get_buffer_offset(info, &info->pixmap, size);
+
+        if (fbcon_cursor->enable) {
+                switch (fbcon_cursor->rop) {
+                case ROP_XOR:
+                        for (i = 0; i < dsize; i++)
+                                src[i] = image->data[i] ^ fbcon_cursor->mask[i];
+                        break;
+                case ROP_COPY:
+                default:
+                        for (i = 0; i < dsize; i++)
+                                src[i] = image->data[i] & fbcon_cursor->mask[i];
+                        break;
+                }
+        } else
+                memcpy(src, image->data, dsize);
+
+        fb_pad_aligned_buffer(dst, d_pitch, src, s_pitch, image->height);
+        image->data = dst;
+        info->fbops->fb_imageblit(info, image);
+        return 0;
+
+    }
+    else{
+	ioctl_cursor = 1;
+
+    	/*if (cursor->width > 16 || cursor->height > 16){
+	DPRINTK("%s width %d or heright %d error\n",__FUNCTION__,cursor->width,cursor->height);
+	return -ENXIO;
+    	}*/
+
+    	if (cursor->flags & CURSOR_OFF)
+        	outl(inl(CURSORXYLOC) & ~0x00008000, CURSORXYLOC);
+
+    	if (cursor->flags & CURSOR_SETSHAPE) {
+        	copy_from_user(cursor_data, cursor->data,
+	    		cursor->width * cursor->height / 4);
+		save = inl(CURSORXYLOC);
+		outl(save & ~0x00008000, CURSORXYLOC);
+
+        	outl(virt_to_phys(cursor_data), CURSOR_ADR_START);
+        	outl(virt_to_phys(cursor_data), CURSOR_ADR_RESET);
+		outl(((cursor->width - 1) & 0x30) << 4 | ((cursor->height - 1) << 2) |
+	     		((cursor->width - 1) >> 4), CURSORSIZE);
+		outl(save, CURSORXYLOC);
+
+    	}
+
+    	if (cursor->flags & CURSOR_SETCOLOR) {
+		outl(cursor->color1, CURSORCOLOR1);
+		outl(cursor->color2, CURSORCOLOR2);
+		outl(cursor->blinkcolor1, CURSORBLINK1);
+		outl(cursor->blinkcolor2, CURSORBLINK2);
+    	}
+
+    	if (cursor->flags & CURSOR_BLINK) {
+        	if (cursor->blinkrate)
+            		outl(0x00000100 | cursor->blinkrate, CURSORBLINK);
+        	else
+	    		outl(0x0000000FF, CURSORBLINK);
+    	}
+
+    	if (cursor->flags & CURSOR_MOVE) {
+       		x = (inl(HACTIVESTRTSTOP) & 0x000007ff) - cursor->dx - 2;
+        	y = (inl(VACTIVESTRTSTOP) & 0x000007ff) - cursor->dy;
+        	outl((inl(CURSORXYLOC) & 0x8000) | (y << 16) | x, CURSORXYLOC);
+    	}
+
+    	if(cursor->flags & CURSOR_ON)
+		outl(inl(CURSORXYLOC) | 0x00008000, CURSORXYLOC);
+
+	return 0;
+    }
+}
+
+
+
+static inline void
+ep93xxfb_palette_write(u_int regno, u_int red, u_int green,
+                       u_int blue, u_int trans)
+{
+    unsigned int cont, i, pal;
+    DPRINTK("ep93xxfb_palette_write - enter\n");
+    pal = ((red & 0xFF00) << 8) | (green & 0xFF00) | ((blue & 0xFF00) >> 8);
+    pseudo_palette[regno] = pal;
+    outl( pal, ( COLOR_LUT + ( regno << 2 )));
+    cont = inl( LUTCONT );
+
+    if (( cont & LUTCONT_STAT && cont & LUTCONT_RAM1 ) ||
+        ( !( cont & LUTCONT_STAT ) && !( cont&LUTCONT_RAM1 ))) {
+	for ( i = 0; i < 256; i++ ) {
+	    outl( pseudo_palette[i], ( COLOR_LUT + ( i << 2 )) );
+	}
+        outl( cont ^ LUTCONT_RAM1, LUTCONT );
+    }
+}
+
+int ep93xxfb_setcolreg(unsigned regno, unsigned red, unsigned green,
+			   unsigned blue, unsigned transp,
+			   struct fb_info *info)
+{
+
+#define CNVT_TOHW(val,width) ((((val)<<(width))+0x7FFF-(val))>>16)
+
+    switch ( info->fix.visual )
+    {
+	case FB_VISUAL_PSEUDOCOLOR:
+	    ep93xxfb_palette_write(regno, red, green, blue, transp);
+	    break;
+	case FB_VISUAL_TRUECOLOR:
+	    if (regno >= 16)
+	        return 1;
+            red = CNVT_TOHW(red, info->var.red.length);
+            green = CNVT_TOHW(green, info->var.green.length);
+            blue = CNVT_TOHW(blue, info->var.blue.length);
+            transp = CNVT_TOHW(transp, info->var.transp.length);
+            ((u32 *)(info->pseudo_palette))[regno] =
+                    (red << info->var.red.offset) |
+                    (green << info->var.green.offset) |
+                    (blue << info->var.blue.offset) |
+                    (transp << info->var.transp.offset);
+      	    break;
+        case FB_VISUAL_DIRECTCOLOR:
+            red = CNVT_TOHW(red, 8);
+	    green = CNVT_TOHW(green, 8);
+	    blue = CNVT_TOHW(blue, 8);
+	    transp = CNVT_TOHW(transp, 8);
+	    break;
+    }
+#undef CNVT_TOHW
+    return 0;
+}
+
+static int ep93xx_pan_display(struct fb_var_screeninfo *var,
+			 struct fb_info *info)
+{
+    DPRINTK("ep93xx_pan_display - enter\n");
+
+    if (var->yoffset < 0
+        || var->yoffset + var->yres > info->var.yres_virtual
+        || var->xoffset)
+	    return -EINVAL;
+
+    outl(epinfo.fb_phys + info->fix.line_length * var->yoffset
+	 , VIDSCRNPAGE);
+
+    info->var.xoffset = var->xoffset;
+    info->var.yoffset = var->yoffset;
+
+    DPRINTK("ep93xx_pan_display - exit\n");
+    return 0;
+}
+
+
+static int
+ep93xxfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
+{
+    struct fb_var_screeninfo tmp_var;
+    unsigned long pclk;
+    DPRINTK("ep93xxfb_check_var - enter\n");
+
+    if( vout != 0) {
+  printk("  ep93xxfb_check_var - vout != 0\n");
+	return -EINVAL;
+    }
+
+    memcpy (&tmp_var, var, sizeof (tmp_var));
+
+    if( (tmp_var.vmode & FB_VMODE_MASK) != FB_VMODE_NONINTERLACED ) {
+	printk("  ep93xxfb_check_var - unsupported video mode\n");
+	return -EINVAL;
+    }
+
+    if( ((tmp_var.xres * tmp_var.yres * tmp_var.bits_per_pixel) / 8) >
+	  MAX_FBMEM_SIZE ) {
+	printk("  ep93xxfb_check_var - memory error \n");
+	return -ENOMEM;
+    }
+
+    if( ((tmp_var.xres_virtual * tmp_var.yres_virtual * tmp_var.bits_per_pixel) / 8) >
+          MAX_FBMEM_SIZE ) {
+	printk("  ep93xxfb_check_var - memory error \n");
+        return -ENOMEM;
+    }
+
+    pclk = 1000 * (1000000000 / tmp_var.pixclock);
+
+    if( pclk > ep93xx_get_max_video_clk() ) {
+        printk("  ep93xxfb_check_var - pixel clock error %lu\n",pclk);
+	return -EINVAL;
+    }
+
+    if (var->xres_virtual != var->xres)
+	var->xres_virtual = var->xres;
+    if (var->yres_virtual < var->yres)
+        var->yres_virtual = var->yres;
+
+    if (var->xoffset < 0)
+        var->xoffset = 0;
+    if (var->yoffset < 0)
+        var->yoffset = 0;
+
+    switch (tmp_var.bits_per_pixel) {
+	case 8:
+	    break;
+        case 16:
+	    break;
+        case 24:
+            break;
+        case 32:
+	    break;
+	default:
+	    return -EINVAL;
+    }
+
+    DPRINTK("ep93xxfb_check_var - exit\n");
+    return 0;
+}
+
+
+static int ep93xxfb_set_par(struct fb_info *info)
+{
+    struct fb_var_screeninfo tmp_var;
+    unsigned long attribs;
+
+    DPRINTK("ep93xxfb_set_par - enter\n");
+
+    if( ep93xxfb_check_var(&info->var,info) < 0 )
+        return -EINVAL;
+
+    if( !ep93xxfb_setcol(info,info->var.bits_per_pixel) )
+	return -EINVAL;
+
+
+	info->fix.line_length = (info->var.xres * info->var.bits_per_pixel) / 8;
+
+    ep93xxfb_blank( 1 , info );
+
+    memcpy(&tmp_var,&info->var,sizeof(tmp_var));
+
+    epinfo.xres = tmp_var.xres;
+    epinfo.xsync = tmp_var.hsync_len;
+    epinfo.xfp = tmp_var.right_margin;
+    epinfo.xbp = tmp_var.left_margin;
+    epinfo.xtotal = epinfo.xres + epinfo.xsync +
+                    epinfo.xfp + epinfo.xbp;
+
+    epinfo.yres = tmp_var.yres;
+    epinfo.ysync = tmp_var.vsync_len;
+    epinfo.yfp = tmp_var.lower_margin;
+    epinfo.ybp = tmp_var.upper_margin;
+    epinfo.ytotal = epinfo.yres + epinfo.ysync +
+		    epinfo.yfp + epinfo.ybp;
+
+    epinfo.pixclock = tmp_var.pixclock ;
+    epinfo.refresh = 1000 * (1000000000 / tmp_var.pixclock) ;
+
+    if( epinfo.refresh > ep93xx_get_max_video_clk())
+	epinfo.refresh = ep93xx_get_max_video_clk();
+    epinfo.bpp = tmp_var.bits_per_pixel;
+
+    ep93xxfb_setclk();
+    ep93xxfb_timing_signal_generation();
+
+    // set video memory parameters
+    outl(epinfo.fb_phys, VIDSCRNPAGE);
+    outl(epinfo.yres , SCRNLINES);
+    outl(((epinfo.xres * epinfo.bpp) / 32) - 1, LINELENGTH);
+    outl((epinfo.xres * epinfo.bpp) / 32, VLINESTEP);
+
+    // set pixel mode
+    ep93xxfb_pixelmod(epinfo.bpp);
+
+    attribs = 0;
+#ifdef CONFIG_EP93XX_SDCS0
+    attribs |= 0 << VIDEOATTRIBS_SDSEL_SHIFT;
+#endif
+#ifdef CONFIG_EP93XX_SDCS1
+    attribs |= 1 << VIDEOATTRIBS_SDSEL_SHIFT;
+#endif
+#ifdef CONFIG_EP93XX_SDCS2
+    attribs |= 2 << VIDEOATTRIBS_SDSEL_SHIFT;
+#endif
+#ifdef CONFIG_EP93XX_SDCS3
+    attribs |= 3 << VIDEOATTRIBS_SDSEL_SHIFT;
+#endif
+
+    attribs |= VIDEOATTRIBS_INVCLK;
+    if( tmp_var.sync & FB_SYNC_HOR_HIGH_ACT )
+        attribs |= VIDEOATTRIBS_HSPOL;
+    if( tmp_var.sync & FB_SYNC_VERT_HIGH_ACT )
+        attribs |= VIDEOATTRIBS_VCPOL;
+
+    ep93xxfb_outl(attribs, VIDEOATTRIBS);
+    ep93xxfb_blank( 0 , info );
+
+    DPRINTK("ep93xxfb_set_par - exit\n");
+
+    return 0;
+}
+
+
+static int ep93xxfb_blank(int blank_mode,struct fb_info *info)
+{
+    unsigned long attribs;
+    DPRINTK("ep93xxfb_blank - enter\n");
+    attribs = inl(VIDEOATTRIBS);
+
+#ifdef CONFIG_EP93XX_SDCS0
+    attribs |= 0 << VIDEOATTRIBS_SDSEL_SHIFT;
+#endif
+#ifdef CONFIG_EP93XX_SDCS1
+    attribs |= 1 << VIDEOATTRIBS_SDSEL_SHIFT;
+#endif
+#ifdef CONFIG_EP93XX_SDCS2
+    attribs |= 2 << VIDEOATTRIBS_SDSEL_SHIFT;
+#endif
+#ifdef CONFIG_EP93XX_SDCS3
+    attribs |= 3 << VIDEOATTRIBS_SDSEL_SHIFT;
+#endif
+
+    if (blank_mode) {
+	if (epinfo.off)
+            (epinfo.off)( 0 );
+
+	ep93xxfb_outl(attribs & ~(VIDEOATTRIBS_DATAEN |
+                 VIDEOATTRIBS_SYNCEN | VIDEOATTRIBS_PCLKEN |
+		 VIDEOATTRIBS_EN), VIDEOATTRIBS);
+    }
+    else {
+	if (epinfo.clk_src == CLK_INTERNAL)
+	    attribs |= VIDEOATTRIBS_PCLKEN;
+	else
+	    attribs &= ~VIDEOATTRIBS_PCLKEN;
+
+	ep93xxfb_outl(attribs | VIDEOATTRIBS_DATAEN |
+	         VIDEOATTRIBS_SYNCEN | VIDEOATTRIBS_EN,
+	         VIDEOATTRIBS);
+
+	if (epinfo.configure)
+		(epinfo.configure)( epinfo.automods );
+	if (epinfo.on)
+	       (epinfo.on)( 0 );
+    }
+    return 0;
+}
+
+static int ep93xxfb_mmap(struct fb_info *info,struct vm_area_struct *vma)
+{
+    unsigned long off, start, len;
+
+    DPRINTK("ep93xxfb_mmap - enter\n");
+
+    off = vma->vm_pgoff << PAGE_SHIFT;
+    start = info->fix.smem_start;
+    len = PAGE_ALIGN(start & ~PAGE_MASK) + info->fix.smem_len;
+    start &= PAGE_MASK;
+    if ((vma->vm_end - vma->vm_start + off) > len)
+	return -EINVAL;
+
+    off += start;
+    vma->vm_pgoff = off >> PAGE_SHIFT;
+
+    vma->vm_flags |= VM_IO;
+    vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot);
+
+    if (io_remap_pfn_range(vma, vma->vm_start, off >> PAGE_SHIFT,
+	vma->vm_end - vma->vm_start, vma->vm_page_prot)) {
+	DPRINTK("ep93xxfb_mmap error\n");
+	return -EAGAIN;
+    }
+
+    DPRINTK("ep93xxfb_mmap - exit\n");
+    return 0;
+}
+
+static unsigned long ep93xx_get_pll_frequency(unsigned long pll)
+{
+    unsigned long fb1, fb2, ipd, ps, freq;
+
+    if (pll == 1)
+	pll = inl(EP93XX_SYSCON_CLOCK_SET1);
+    else if (pll == 2)
+	pll = inl(EP93XX_SYSCON_CLOCK_SET2);
+    else
+	return 0;
+
+    ps = (pll & SYSCON_CLKSET1_PLL1_PS_MASK) >>	SYSCON_CLKSET1_PLL1_PS_SHIFT;
+    fb1 = ((pll & SYSCON_CLKSET1_PLL1_X1FBD1_MASK) >> SYSCON_CLKSET1_PLL1_X1FBD1_SHIFT);
+    fb2 = ((pll & SYSCON_CLKSET1_PLL1_X2FBD2_MASK) >> SYSCON_CLKSET1_PLL1_X2FBD2_SHIFT);
+    ipd = ((pll & SYSCON_CLKSET1_PLL1_X2IPD_MASK) >> SYSCON_CLKSET1_PLL1_X2IPD_SHIFT);
+
+    freq = (((0x00e10000 * (fb1+1)) / (ipd+1)) * (fb2+1)) >> ps;
+    return freq;
+}
+
+static int ep93xx_get_max_video_clk()
+{
+    unsigned long f,freq = 0;
+
+    freq = 14745600 / 4;
+    f = ep93xx_get_pll_frequency(1) / 4;
+    if ( f > freq )
+	freq = f;
+    f = ep93xx_get_pll_frequency(2) / 4;
+    if ( f > freq )
+	freq = f;
+
+    return freq;
+}
+
+static int ep93xx_set_video_div(unsigned long freq)
+{
+    unsigned long pdiv = 0, div = 0, psel = 0, esel = 0;
+    unsigned long err, f, i, j, k;
+
+    err = -1;
+
+    for (i = 0; i < 3; i++) {
+	if (i == 0)
+	    f = 14745600 * 2;
+	else if (i == 1)
+	    f = ep93xx_get_pll_frequency(1) * 2;
+	else
+	    f = ep93xx_get_pll_frequency(2) * 2;
+
+	for (j = 4; j <= 6; j++) {
+	    k = f / (freq * j);
+	    if (k < 2)
+		continue;
+
+	    if (abs(((f / (j * k))) - freq ) < err ) {
+		pdiv = j - 3;
+		div = k;
+		psel = (i == 2) ? 1 : 0;
+		esel = (i == 0) ? 0 : 1;
+		err = (f / (j * k)) - freq;
+	    }
+	}
+    }
+
+    if (err == -1)
+	return -1;
+
+    SysconSetLocked(SYSCON_VIDDIV,SYSCON_VIDDIV_VENA | (esel ? SYSCON_VIDDIV_ESEL : 0) |
+                       (psel ? SYSCON_VIDDIV_PSEL : 0) |
+                       (pdiv << SYSCON_VIDDIV_PDIV_SHIFT) |
+                       (div << SYSCON_VIDDIV_VDIV_SHIFT)
+                  );
+
+    return freq + err;
+}
+
+static void ep93xxfb_pixelmod(int bpp)
+{
+    unsigned long tmpdata = 0;
+
+    DPRINTK("ep93xxfb_pixelmod %dbpp -enter\n",bpp);
+    switch(bpp) {
+	case 8:
+            tmpdata = PIXELMODE_P_8BPP |
+		      PIXELMODE_S_1PPCMAPPED |
+                      PIXELMODE_C_LUT;
+	    epinfo.pixformat = PIXEL_FORMAT_8;
+	    break;
+	case 16:
+	    tmpdata = PIXELMODE_P_16BPP |
+		      PIXELMODE_S_1PPCMAPPED |
+		      PIXELMODE_C_565;
+            epinfo.pixformat = PIXEL_FORMAT_16;
+	    break;
+	case 24:
+            tmpdata = PIXELMODE_P_24BPP |
+	              PIXELMODE_S_1PPC |
+		      PIXELMODE_C_888;
+            epinfo.pixformat = PIXEL_FORMAT_24;
+	    break;
+        case 32:
+            tmpdata = PIXELMODE_P_32BPP |
+		      PIXELMODE_S_1PPC |
+		      PIXELMODE_C_888;
+            epinfo.pixformat = PIXEL_FORMAT_32;
+	    break;
+	default:
+	    break;
+    }
+    outl(tmpdata,PIXELMODE);
+}
+
+static void ep93xxfb_timing_signal_generation(void)
+{
+    unsigned long vlinestotal,vsyncstart,vsyncstop,
+		  vactivestart,vactivestop,
+		  vblankstart,vblankstop,
+		  vclkstart,vclkstop;
+
+    unsigned long hclkstotal,hsyncstart,hsyncstop,
+                  hactivestart,hactivestop,
+		  hblankstart,hblankstop,
+		  hclkstart,hclkstop;
+
+    DPRINTK("ep93xxfb_timing_signal_generation - enter\n");
+
+    vlinestotal = epinfo.ytotal - 1;
+    vsyncstart = vlinestotal;
+    vsyncstop = vlinestotal - epinfo.ysync;
+    vblankstart = vlinestotal - epinfo.ysync - epinfo.ybp;
+    vblankstop = epinfo.yfp - 1;
+    vactivestart = vblankstart;
+    vactivestop = vblankstop;
+    vclkstart = vlinestotal;
+    vclkstop = vlinestotal + 1;
+
+    hclkstotal = epinfo.xtotal - 1;
+    hsyncstart = hclkstotal;
+    hsyncstop = hclkstotal - epinfo.xsync;
+    hblankstart = hclkstotal - epinfo.xsync - epinfo.xbp;
+    hblankstop = epinfo.xfp - 1;
+    hactivestart = hblankstart;
+    hactivestop = hblankstop;
+    hclkstart = hclkstotal ;
+    hclkstop = hclkstotal ;
+
+    ep93xxfb_outl(0, VIDEOATTRIBS);
+
+    ep93xxfb_outl( vlinestotal , VLINESTOTAL );
+    ep93xxfb_outl( vsyncstart + (vsyncstop << 16), VSYNCSTRTSTOP );
+    ep93xxfb_outl( vactivestart + (vactivestop << 16), VACTIVESTRTSTOP );
+    ep93xxfb_outl( vblankstart + (vblankstop << 16), VBLANKSTRTSTOP );
+    ep93xxfb_outl( vclkstart + (vclkstop << 16), VCLKSTRTSTOP );
+
+    ep93xxfb_outl( hclkstotal , HCLKSTOTAL );
+    ep93xxfb_outl( hsyncstart + (hsyncstop << 16), HSYNCSTRTSTOP );
+    ep93xxfb_outl( hactivestart + (hactivestop << 16) , HACTIVESTRTSTOP );
+    ep93xxfb_outl( hblankstart + (hblankstop << 16) , HBLANKSTRTSTOP );
+    ep93xxfb_outl( hclkstart + (hclkstop << 16) , HCLKSTRTSTOP );
+
+    ep93xxfb_outl(0, LINECARRY);
+
+}
+
+static int ep93xxfb_setcol(struct fb_info *info, int bpp)
+{
+
+    DPRINTK("ep93xxfb_setcol %dbpp\n",bpp);
+    switch(bpp) {
+	case 8:
+            info->var.bits_per_pixel = 8;
+	    info->var.red.length = 8;
+	    info->var.green.length = 8;
+	    info->var.blue.length = 8;
+    	    info->fix.visual = FB_VISUAL_PSEUDOCOLOR;
+	    break;
+	case 16:
+            info->var.bits_per_pixel = 16;
+	    info->var.red.offset = 11;
+	    info->var.red.length = 5;
+	    info->var.green.offset = 5;
+	    info->var.green.length = 6;
+	    info->var.blue.offset = 0;
+	    info->var.blue.length = 5;
+    	    info->fix.visual = FB_VISUAL_TRUECOLOR;
+	    break;
+	case 24:
+	    info->var.bits_per_pixel = 24;
+	    info->var.red.length = 8;
+	    info->var.blue.length = 8;
+	    info->var.green.length = 8;
+	    info->var.red.offset = 16;
+	    info->var.green.offset = 8;
+	    info->var.blue.offset = 0;
+	    info->fix.visual = FB_VISUAL_TRUECOLOR;
+	    break;
+	case 32:
+            info->var.bits_per_pixel = 32;
+	    info->var.red.length = 8;
+	    info->var.blue.length = 8;
+	    info->var.green.length = 8;
+	    info->var.transp.length = 0;
+	    info->var.red.offset = 16;
+	    info->var.green.offset = 8;
+	    info->var.blue.offset = 0;
+	    info->var.transp.offset = 0;
+	    info->fix.visual = FB_VISUAL_TRUECOLOR;
+	    break;
+	default:
+	    return 0;
+    }
+    return 1;
+}
+
+static int ep93xxfb_setclk()
+{
+    unsigned long calc_clk,act_clk;
+
+    if ( epinfo.clk_src == CLK_INTERNAL ) {
+	SysconSetLocked(EP93XX_SYSCON_DEVICE_CONFIG,inl(EP93XX_SYSCON_DEVICE_CONFIG) & ~EP93XX_SYSCON_DEVICE_CONFIG_CRUNCH_ENABLE);
+        calc_clk = epinfo.refresh;
+        act_clk = ep93xx_set_video_div( calc_clk );
+	if ( act_clk == -1 )
+               return -ENODEV;
+
+	epinfo.refresh = act_clk;
+	epinfo.pixclock = 1000000000 / (act_clk / 1000);
+    }
+    else {
+	SysconSetLocked(SYSCON_VIDDIV,0);
+	SysconSetLocked(EP93XX_SYSCON_DEVICE_CONFIG,inl(EP93XX_SYSCON_DEVICE_CONFIG) | EP93XX_SYSCON_DEVICE_CONFIG_CRUNCH_ENABLE);
+
+    }
+
+    return 0;
+}
+
+
+static void ep93xxfb_get_par(struct fb_info *info)
+{
+
+    DPRINTK("ep93xxfb_get_par - enter\n");
+    epinfo.configure = NULL;
+    epinfo.on = NULL;
+    epinfo.off = NULL;
+
+    switch( vout ) {
+	case LCD_OUT:
+            epinfo.on = philips_lb064v02_on;
+	    epinfo.off = philips_lb064v02_off;
+
+	case CRT_OUT:
+    	    epinfo.xres = ep93xxfb_vmods[vmode].hres;
+    	    epinfo.xsync = ep93xxfb_vmods[vmode].hsync;
+    	    epinfo.xfp = ep93xxfb_vmods[vmode].hfp;
+    	    epinfo.xbp = ep93xxfb_vmods[vmode].hbp;
+    	    epinfo.xtotal = epinfo.xres + epinfo.xsync +
+			    epinfo.xfp + epinfo.xbp;
+
+    	    epinfo.yres = ep93xxfb_vmods[vmode].vres;
+    	    epinfo.ysync = ep93xxfb_vmods[vmode].vsync;
+    	    epinfo.yfp = ep93xxfb_vmods[vmode].vfp;
+    	    epinfo.ybp = ep93xxfb_vmods[vmode].vbp;
+    	    epinfo.ytotal = epinfo.yres + epinfo.ysync +
+        	        epinfo.yfp + epinfo.ybp;
+
+	    epinfo.refresh = ep93xxfb_vmods[vmode].refresh;
+    	    epinfo.refresh = epinfo.xtotal * epinfo.ytotal * epinfo.refresh;
+	    epinfo.pixclock = 1000000000 / ( epinfo.refresh / 1000);
+	    epinfo.bpp = depth;
+
+    	    epinfo.clk_src = ep93xxfb_vmods[vmode].clk_src;
+    	    epinfo.clk_edge = ep93xxfb_vmods[vmode].clk_edge;
+    	    epinfo.pol_blank = ep93xxfb_vmods[vmode].pol_blank;
+    	    epinfo.pol_xsync = ep93xxfb_vmods[vmode].pol_hsync;
+    	    epinfo.pol_ysync = ep93xxfb_vmods[vmode].pol_vsync;
+	    break;
+
+    }
+}
+
+static int ep93xxfb_alloc_videomem(void)
+{
+    unsigned long adr,size,pgsize;
+    int order;
+
+    DPRINTK("ep93xxfb_alloc_videomem - enter \n");
+
+    epinfo.fb_log = NULL;
+    epinfo.fb_size = PAGE_ALIGN( MAX_FBMEM_SIZE/*ep93xxfb_vmods[vmode].hres * ep93xxfb_vmods[vmode].vres * (depth / 8)*/ );
+    order = get_order( epinfo.fb_size );
+    epinfo.fb_log = (void*) __get_free_pages( GFP_KERNEL, order );
+
+    if (epinfo.fb_log) {
+	epinfo.fb_phys = __virt_to_phys((int) epinfo.fb_log );
+        adr = (unsigned long)epinfo.fb_log;
+	size = epinfo.fb_size;
+	pgsize = 1 << order;
+        do {
+            adr += pgsize;
+            SetPageReserved(virt_to_page(adr));
+	} while(size -= pgsize);
+    }
+    else{
+        printk("%s memory fail \n",__FUNCTION__);
+        return -ENOMEM;
+    }
+
+    memset(epinfo.fb_log,0x00,epinfo.fb_size);
+    DPRINTK("   fb_log_addres = 0x%x\n",epinfo.fb_log);
+    DPRINTK("   fb_phys_address = 0x%x\n",epinfo.fb_phys);
+    DPRINTK("   fb_size = %lu\n",epinfo.fb_size);
+    DPRINTK("   fb_page_order = %d\n",order);
+    DPRINTK("ep93xxfb_alloc_videomem - exit \n");
+    return 0;
+}
+
+static void ep93xxfb_release_videomem(void)
+{
+    unsigned long adr,size,psize;
+    int order;
+
+    DPRINTK("ep93xxfb_release_videomem - enter \n");
+
+    if (epinfo.fb_log) {
+	order = get_order(epinfo.fb_size);
+        adr = (unsigned long)epinfo.fb_log;
+        size = epinfo.fb_size;
+	psize = 1 << order ;
+        do {
+            adr += psize;
+            ClearPageReserved(virt_to_page(adr));
+	} while(size -= psize);
+	free_pages((unsigned long)epinfo.fb_log, order );
+    }
+
+
+    DPRINTK("ep93xxfb_release_videomem - exit \n");
+}
+
+static void ep93xxfb_setinfo(struct fb_info *info)
+{
+
+    info->pseudo_palette = pseudo_palette;
+    info->var.xres = epinfo.xres;
+    info->var.yres = epinfo.yres;
+    info->var.xres_virtual = epinfo.xres;
+    info->var.yres_virtual = epinfo.yres;
+
+    ep93xxfb_setcol( info, depth );
+
+    info->var.activate = FB_ACTIVATE_NOW;
+    info->var.left_margin = epinfo.xbp;
+    info->var.right_margin = epinfo.xfp;
+    info->var.upper_margin = epinfo.ybp;
+    info->var.lower_margin = epinfo.yfp;
+    info->var.hsync_len = epinfo.xsync;
+    info->var.vsync_len = epinfo.ysync;
+
+    if( epinfo.pol_xsync == POL_HIGH )
+        info->var.sync |= FB_SYNC_HOR_HIGH_ACT;
+    if( epinfo.pol_ysync == POL_HIGH )
+        info->var.sync |= FB_SYNC_VERT_HIGH_ACT;
+
+    info->var.vmode = FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP;
+    info->fix.smem_start = epinfo.fb_phys;
+    info->fix.smem_len = epinfo.fb_size;
+    info->fix.type = FB_TYPE_PACKED_PIXELS;
+    info->fix.line_length = epinfo.xres * (epinfo.bpp / 8);
+    info->screen_base = epinfo.fb_log;
+    info->var.pixclock = epinfo.pixclock;
+    info->fix.ypanstep = 1;
+    info->fix.ywrapstep = 1;
+
+}
+
+static int ep93xxfb_config(struct fb_info *info)
+{
+    unsigned long attribs;
+
+    DPRINTK("ep93xxfb_config - enter\n");
+
+    ep93xxfb_get_par( info );
+    if( ep93xxfb_alloc_videomem() != 0 ) {
+        printk("Unable to allocate video memory\n");
+        return -ENOMEM;
+    }
+
+    if( ep93xxfb_setclk() != 0 ) {
+	printk("Unable to set pixel clock\n");
+        ep93xxfb_release_videomem();
+	return -ENODEV;
+    }
+
+    SysconSetLocked(EP93XX_SYSCON_DEVICE_CONFIG, inl(EP93XX_SYSCON_DEVICE_CONFIG)  |EP93XX_SYSCON_DEVCFG_RasOnP3);
+    ep93xxfb_timing_signal_generation();
+
+    /* set video memory parameters */
+    outl(epinfo.fb_phys, VIDSCRNPAGE);
+    outl(epinfo.yres , SCRNLINES);
+    outl(((epinfo.xres * epinfo.bpp) / 32) - 1, LINELENGTH);
+    outl((epinfo.xres * epinfo.bpp) / 32, VLINESTEP);
+
+
+    /* set pixel mode */
+    ep93xxfb_pixelmod(depth);
+
+    attribs = 0;
+
+#ifdef CONFIG_EP93XX_SDCS0
+    attribs |= 0 << VIDEOATTRIBS_SDSEL_SHIFT;
+#endif
+#ifdef CONFIG_EP93XX_SDCS1
+    attribs |= 1 << VIDEOATTRIBS_SDSEL_SHIFT;
+#endif
+#ifdef CONFIG_EP93XX_SDCS2
+    attribs |= 2 << VIDEOATTRIBS_SDSEL_SHIFT;
+#endif
+#ifdef CONFIG_EP93XX_SDCS3
+    attribs |= 3 << VIDEOATTRIBS_SDSEL_SHIFT;
+#endif
+
+    if(epinfo.clk_edge == EDGE_RISING)
+	attribs |= VIDEOATTRIBS_INVCLK;
+    if(epinfo.pol_blank == POL_HIGH)
+	attribs |= VIDEOATTRIBS_BLKPOL;
+    if(epinfo.pol_xsync == POL_HIGH)
+	attribs |= VIDEOATTRIBS_HSPOL;
+    if(epinfo.pol_ysync == POL_HIGH)
+	attribs |= VIDEOATTRIBS_VCPOL;
+
+    ep93xxfb_outl(attribs, VIDEOATTRIBS);
+    ep93xxfb_setinfo( info );
+
+    if(epinfo.configure)
+	(epinfo.configure)( epinfo.automods );
+
+    ep93xxfb_blank( 0 , info );
+
+    DPRINTK("ep93xxfb_config - exit\n");
+    return 0;
+}
+
+int ep93xxfb_ioctl(struct fb_info *info,unsigned int cmd, unsigned long arg)
+{
+    struct fb_fillrect fill;
+    struct fb_copyarea cparea;
+    struct fb_image img;
+    struct ep93xx_line line;
+    struct ep93xx_cursor cursor;
+
+    switch (cmd) {
+        case FBIO_EP93XX_CURSOR:
+            copy_from_user(&cursor, (void *)arg, sizeof(struct ep93xx_cursor));
+	    ep93xxfb_cursor(info,&cursor);
+	    break;
+	case FBIO_EP93XX_LINE:
+            copy_from_user(&line, (void *)arg, sizeof(struct ep93xx_line));
+	    ep93xxfb_line(info,&line);
+	    break;
+	case FBIO_EP93XX_FILL:
+	    copy_from_user(&fill, (void *)arg, sizeof(struct fb_fillrect));
+	    ep93xxfb_fillrect(info,&fill);
+	    break;
+	case FBIO_EP93XX_BLIT:
+            copy_from_user(&img, (void *)arg, sizeof(struct fb_image));
+	    ep93xxfb_imageblit(info, &img);
+	    break;
+        case FBIO_EP93XX_COPY:
+	    copy_from_user(&cparea, (void *)arg, sizeof(struct fb_copyarea));
+	    ep93xxfb_copyarea(info,&cparea);
+	    break;
+        default:
+	    return -EFAULT;
+    }
+    return 0;
+}
+
+
+static struct fb_ops ep93xxfb_ops = {
+    .owner          = THIS_MODULE,
+    .fb_setcolreg   = ep93xxfb_setcolreg,
+    .fb_check_var   = ep93xxfb_check_var,
+    .fb_set_par     = ep93xxfb_set_par,
+    .fb_blank       = ep93xxfb_blank,
+    .fb_pan_display = ep93xx_pan_display,
+    .fb_fillrect    = ep93xxfb_fillrect,
+    .fb_copyarea    = ep93xxfb_copyarea,
+    .fb_imageblit   = cfb_imageblit,
+    .fb_cursor      = ep93xxfb_cursor,
+    .fb_ioctl       = ep93xxfb_ioctl,
+    .fb_mmap        = ep93xxfb_mmap,
+};
+
+
+static struct resource ep93xxfb_raster_resources = {
+    .start          = EP93XX_RASTER_PHYS_BASE,
+    .end            = EP93XX_RASTER_PHYS_BASE + 0x1ffff,
+    .flags          = IORESOURCE_MEM,
+};
+
+
+static int __init ep93xxfb_probe(struct platform_device *device)
+{
+    struct fb_info *info = NULL;
+    struct resource *res = NULL;
+    int ret = 0;
+    int arb = 0;
+
+    DPRINTK("ep93xxfb_probe - enter \n");
+
+
+    if(!device) {
+	printk("error : to_platform_device\n");
+        return -ENODEV;
+    }
+    res = platform_get_resource( device, IORESOURCE_MEM, 0);
+    if(!res) {
+        printk("error : platform_get_resource \n");
+        return -ENODEV;
+    }
+    cursor_data = kmalloc( 64 * 64 * 2, GFP_KERNEL );
+    memset( cursor_data, 0x00, 64 * 64 * 2 );
+    if(!cursor_data) {
+        printk("Unable to allocate memory for hw_cursor\n");
+	return -ENOMEM;
+    }
+    if (!request_mem_region(res->start,res->end - res->start + 1, FBDEV_NAME ))
+	return -EBUSY;
+
+    info = framebuffer_alloc(sizeof(u32) * 256, &device->dev);
+
+    if(!info) {
+	printk("Unable to allocate memory for frame buffer\n");
+	return -ENOMEM;
+    }
+
+    info->flags = FBINFO_DEFAULT;
+    strncpy(info->fix.id, FBDEV_NAME, sizeof(info->fix.id));
+    info->fix.mmio_start = res->start;
+    info->fix.mmio_len = res->end - res->start + 1;
+    info->fbops = &ep93xxfb_ops;
+    info->pseudo_palette = info->par;
+    info->state = FBINFO_STATE_RUNNING;
+
+    if (fb_alloc_cmap(&info->cmap, 256, 0) < 0) {
+	ret = -ENOMEM;
+	goto fbuff;
+    }
+
+    if ((ret = ep93xxfb_config(info)) < 0)
+	goto clmap;
+
+    if (register_framebuffer(info) < 0) {
+	printk(KERN_ERR "Unable to register ep93xxfb frame buffer\n");
+	ret = -EINVAL;
+	goto clmap;
+    }
+    platform_set_drvdata(device, info);
+    printk(KERN_INFO "fb%d: EP93xx frame buffer at %dx%dx%dbpp\n", info->node,
+		info->var.xres, info->var.yres, info->var.bits_per_pixel);
+
+    /*change the raster arb to the highest one--Bo*/
+    arb = inl(EP93XX_SYSCON_BMAR);
+    arb = (arb & 0x3f8) | 0x01;
+    outl(arb,EP93XX_SYSCON_BMAR);
+
+    DPRINTK("ep93xxfb_probe - exit \n");
+    return 0;
+
+clmap:
+    fb_dealloc_cmap(&info->cmap);
+
+fbuff:
+    framebuffer_release(info);
+    return ret;
+}
+
+static int ep93xxfb_remove(struct platform_device *device)
+{
+    struct resource *res;
+    struct fb_info *info;
+    struct ep93xx_cursor cursor;
+
+    DPRINTK("ep93xxfb_remove - enter \n");
+
+    info = platform_get_drvdata(device);
+
+    ep93xxfb_release_videomem();
+
+    res = platform_get_resource( device, IORESOURCE_MEM, 0);
+    release_mem_region(res->start, res->end - res->start + 1);
+
+    platform_set_drvdata(device, NULL);
+    unregister_framebuffer(info);
+
+    fb_dealloc_cmap(&info->cmap);
+    framebuffer_release(info);
+
+    cursor.flags = CURSOR_OFF;
+    ep93xxfb_cursor(info,&cursor);
+    if(cursor_data!=NULL)
+	kfree(cursor_data);
+
+    ep93xxfb_blank( 1, info );
+
+    DPRINTK("ep93xxfb_remove - exit \n");
+    return 0;
+}
+
+static void ep93xxfb_platform_release(struct device *device)
+{
+    DPRINTK("ep93xxfb_platform_release - enter\n");
+}
+
+static int ep93xxfb_check_param(void)
+{
+
+    switch(vout) {
+	case CRT_OUT:
+	    if( vmode >=(sizeof(ep93xxfb_vmods)/sizeof(ep93xxfb_vmods[0]))){
+        	vmode = 1;
+        	depth = DEFAULT_BPP;
+	    	return 0;
+	    }
+	    break;
+        case LCD_OUT:
+	    if( vmode != 0 || depth != 16 ) {
+        	vmode = 0;
+        	depth = DEFAULT_BPP;
+	    	return 0;
+	    }
+	    break;
+	default:
+	    vmode = DEFAULT_MODE;
+	    depth = DEFAULT_BPP;
+	    vout = DEFAULT_OUT;
+	    return 0;
+	    break;
+    }
+
+    if(!((depth == 8) || (depth == 16) || (depth == 24) || (depth == 32)))
+	depth = DEFAULT_BPP;
+
+    return 1;
+}
+
+int __init ep93xxfb_setup(char *options)
+{
+    char *opt;
+
+    DPRINTK("ep93xxfb_setup - %s\n",options);
+
+    if (!options || !*options)
+	return 0;
+
+    while ((opt = strsep(&options, ",")) != NULL) {
+	if (!strncmp(opt, "vout=", 5))
+	    vout = simple_strtoul(opt + 5, NULL, 0);
+	else if (!strncmp(opt, "vmode=", 6))
+	    vmode = simple_strtoul(opt + 6, NULL, 0);
+	else if (!strncmp(opt, "depth=", 6))
+	    depth = simple_strtoul(opt + 6, NULL, 0);
+    }
+    ep93xxfb_check_param();
+    return 0;
+}
+
+
+static struct platform_driver ep93xxfb_driver = {
+    .probe  = ep93xxfb_probe,
+    .remove = ep93xxfb_remove,
+    .driver = {
+		 .name   = FBDEV_NAME,
+	      },
+};
+
+static struct platform_device ep93xxfb_device = {
+    .name      = FBDEV_NAME,
+    .id        = -1,
+    .dev    = {
+		.release = ep93xxfb_platform_release,
+	      },
+    .num_resources  = 1,
+    .resource       = &ep93xxfb_raster_resources,
+};
+
+int __init ep93xxfb_init(void)
+{
+    int ret = 0;
+    char *option = NULL;
+
+    DPRINTK("ep93xxfb_init - enter\n");
+
+    if (fb_get_options("ep93xxfb", &option))
+            return -ENODEV;
+    ep93xxfb_setup(option);
+
+
+    if( !ep93xxfb_check_param() ) {
+	printk("Unsupported format \n");
+	return -1;
+    }
+    /*Add the Hardware accel irq */
+    outl(0x00000000, BLOCKCTRL);
+    ret = request_irq(IRQ_EP93XX_GRAPHICS, ep93xxfb_irq_handler, IRQF_DISABLED,"graphics",NULL);
+
+    if (ret != 0) {
+    	printk("%s: can't get irq %i, err %d\n",__FUNCTION__, IRQ_EP93XX_GRAPHICS, ret);
+                return -EBUSY;
+    }
+
+    /*-------------------------------*/
+    ret = platform_driver_register(&ep93xxfb_driver);
+
+    if (!ret) {
+	ret = platform_device_register(&ep93xxfb_device);
+	if (ret)
+	    platform_driver_unregister(&ep93xxfb_driver);
+    }
+
+    DPRINTK("ep93xxfb_init - exit\n");
+    return ret;
+}
+
+
+
+static void __exit ep93xxfb_exit(void)
+{
+    DPRINTK("ep93xxfb_exit - enter\n");
+    platform_driver_unregister(&ep93xxfb_driver);
+    platform_device_unregister(&ep93xxfb_device);
+    DPRINTK("ep93xxfb_exit - exit\n");
+}
+
+module_init(ep93xxfb_init);
+module_exit(ep93xxfb_exit);
+
+
+module_param( vmode, int,  S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP);
+MODULE_PARM_DESC(vmode, "Specify the video mode number that should be used");
+module_param( vout , int ,  S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP );
+MODULE_PARM_DESC(vout ,"Specify video output (0 = CRT ,1 = LCD )");
+module_param( depth , int,  S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP);
+MODULE_PARM_DESC(depth ,"Color depth (8,16,24,32)");
+MODULE_LICENSE("GPL");
--- /dev/null
+++ b/drivers/video/ep93xxfb.h
@@ -0,0 +1,236 @@
+#ifndef __EP93XXFB_H__
+#define __EP93XXFB_H__
+
+
+#define POL_HIGH		1
+#define POL_LOW        		0
+#define EDGE_RISING     	1
+#define EDGE_FALLING    	0
+#define CLK_INTERNAL    	1
+#define CLK_EXTERNAL    	0
+
+#define CRT_OUT         	0
+#define LCD_OUT         	1
+#define TV_OUT          	2
+
+#define MAX_XRES                1280
+#define MAX_YRES                1024
+#define MAX_BPP                 16
+#define MAX_FBMEM_SIZE          3686400/*1920000*/
+
+#define MAX_XRES_CRT            MAX_XRES
+#define MAX_YRES_CRT            MAX_YRES
+#define MAX_XRES_SVIDEO         1024
+#define MAX_YRES_SVIDEO         768
+
+#define PIXEL_FORMAT_SHIFT      17
+#define PIXEL_FORMAT_4          ( 1 << PIXEL_FORMAT_SHIFT )
+#define PIXEL_FORMAT_8          ( 2 << PIXEL_FORMAT_SHIFT )
+#define PIXEL_FORMAT_16         ( 4 << PIXEL_FORMAT_SHIFT )
+#define PIXEL_FORMAT_24         ( 6 << PIXEL_FORMAT_SHIFT )
+#define PIXEL_FORMAT_32         ( 7 << PIXEL_FORMAT_SHIFT )
+
+
+struct ep93xxfb_videomodes
+{
+    const char *name;
+
+    unsigned long hres; 	// Horizontal Valid
+    unsigned long hfp;		// Horizontal Front Porch
+    unsigned long hsync;	// Horizontal Sync Width
+    unsigned long hbp;		// Horizontal Back Porch
+
+    unsigned long vres;		// Vertical Valid
+    unsigned long vfp;		// Vertical Front Porch
+    unsigned long vsync;	// Vertical Sync Width
+    unsigned long vbp;		// Vertical Back Porch
+
+    unsigned long refresh;	// Vertical Sync Frequency
+
+    unsigned long clk_src;
+    unsigned long clk_edge;
+    unsigned long pol_blank;
+    unsigned long pol_hsync;
+    unsigned long pol_vsync;
+};
+
+
+struct ep93xxfb_info
+{
+
+
+    dma_addr_t                  fb_phys;
+    void	               *fb_log;
+    unsigned long               fb_size;
+    unsigned long		fb_actsize;
+
+    unsigned long               xtotal;
+    unsigned long               ytotal;
+
+    unsigned int                xres;
+    unsigned int		xfp;
+    unsigned int		xsync;
+    unsigned int		xbp;
+
+    unsigned int                yres;
+    unsigned int		yfp;
+    unsigned int		ysync;
+    unsigned int		ybp;
+    unsigned int                bpp;
+
+    unsigned long 		refresh;
+    unsigned long		pixclock;
+    unsigned long               pixformat;
+
+    unsigned int clk_src;
+    unsigned int clk_edge;
+    unsigned int pol_blank;
+    unsigned int pol_xsync;
+    unsigned int pol_ysync;
+
+    unsigned char automods;
+
+    void (*configure)(unsigned char value);
+    void (*on)(unsigned char value);
+    void (*off)(unsigned char value);
+};
+
+static int  ep93xxfb_setclk(void);
+static int  ep93xx_get_max_video_clk(void);
+static void ep93xxfb_pixelmod(int bpp);
+static void ep93xxfb_timing_signal_generation(void);
+static int  ep93xxfb_blank(int blank_mode,struct fb_info *info);
+
+#define EE_DELAY_USEC                   2
+#define EE_READ_TIMEOUT                 100
+#define CX25871_DEV_ADDRESS             0x88
+#define GPIOG_EEDAT   			2
+#define GPIOG_EECLK     		1
+#define CXMODES_COUNT   		24
+
+struct cx25871_vmodes
+{
+
+    const char          *name;
+    unsigned char       automode;
+    unsigned int        hres;
+    unsigned int        vres;
+    unsigned int        hclktotal;
+    unsigned int        vclktotal;
+    unsigned int        hblank;
+    unsigned int        vblank;
+    unsigned long       clkfrequency;
+
+};
+
+
+int write_reg(unsigned char ucRegAddr, unsigned char ucRegValue);
+void cx25871_on(unsigned char value);
+void cx25871_off(unsigned char value);
+void cx25871_config(unsigned char value);
+
+static void philips_lb064v02_on(unsigned char value);
+static void philips_lb064v02_off(unsigned char value);
+
+
+#define FBIO_EP93XX_CURSOR      0x000046c1
+#define FBIO_EP93XX_LINE        0x000046c2
+#define FBIO_EP93XX_FILL        0x000046c3
+#define FBIO_EP93XX_BLIT        0x000046c4
+#define FBIO_EP93XX_COPY        0x000046c5
+
+
+#define CURSOR_BLINK            0x00000001
+#define CURSOR_MOVE             0x00000002
+#define CURSOR_SETSHAPE         0x00000004
+#define CURSOR_SETCOLOR         0x00000008
+#define CURSOR_ON               0x00000010
+#define CURSOR_OFF              0x00000020
+
+
+/*
+* ioctl(fd, FBIO_EP93XX_CURSOR, ep93xx_cursor *)
+*
+* "data" points to an array of pixels that define the cursor; each row should
+* be a multiple of 32-bit values (i.e. 16 pixels).  Each pixel is two bits,
+* where the values are:
+*
+*     00 => transparent    01 => invert    10 => color1    11 => color2
+*
+* The data is arranged as follows (per word):
+*
+*    bits: |31-30|29-28|27-26|25-24|23-22|21-20|19-18|17-16|
+*   pixel: | 12  | 13  | 14  | 15  |  8  |  9  | 10  | 11  |
+*    bits: |15-14|13-12|11-10| 9-8 | 7-6 | 5-4 | 3-2 | 1-0 |
+*   pixel: |  4  |  5  |  6  |  7  |  0  |  1  |  2  |  3  |
+*
+* Regardless of the frame buffer color depth, "color1", "color2",
+* "blinkcolor1", and "blinkcolor2" are 24-bit colors since the cursor is
+* injected into the data stream right before the video DAC.
+*
+* When "blinkrate" is not zero, pixel value 10 will alternate between "color1"
+* and "blinkcolor1" (similar for pixel value 11 and "color2"/"blinkcolor2").
+*
+* "blinkrate" ranges between 0 and 255.  When 0, blinking is disabled.  255 is
+* the fastest blink rate and 1 is the slowest.
+*
+* Both "width" and "height" must be between 1 and 64; it is preferable to have
+* "width" a multiple of 16.
+*/
+struct ep93xx_cursor {
+    unsigned long flags;
+    unsigned long dx;           // Only used if CURSOR_MOVE is set
+    unsigned long dy;           // Only used if CURSOR_MOVE is set
+    unsigned long width;        // Only used if CURSOR_SETSHAPE is set
+    unsigned long height;       // Only used if CURSOR_SETSHAPE is set
+    const char *data;   // Only used if CURSOR_SETSHAPE is set
+    unsigned long blinkrate;    // Only used if CURSOR_BLINK is set
+    unsigned long color1;       // Only used if CURSOR_SETCOLOR is set
+    unsigned long color2;       // Only used if CURSOR_SETCOLOR is set
+    unsigned long blinkcolor1;  // Only used if CURSOR_SETCOLOR is set
+    unsigned long blinkcolor2;  // Only used if CURSOR_SETCOLOR is set
+};
+
+
+/*
+ * The bits in the flags field of ep93xx_line.
+*/
+/*
+* ioctl(fd, FBIO_EP93XX_LINE, ep93xx_line *)
+*
+* The line starts at ("x1","y1") and ends at ("x2","y2").  This means that
+* when using a pattern, the two coordinates are not transitive (i.e. swapping
+* ("x1","y1") with ("x2","y2") will not necessarily draw the exact same line,
+* pattern-wise).
+*
+* "pattern" is a 2 to 16 bit pattern (since a 1 bit pattern isn't much of a
+* pattern).  The lower 16 bits define the pattern (1 being foreground, 0 being
+* background or transparent), and bits 19-16 define the length of the pattern
+* (as pattern length - 1).  So, for example, "0xf00ff" defines a 16 bit
+* with the first 8 pixels in the foreground color and the next 8 pixels in the
+* background color or transparent.
+*
+* LINE_PRECISE is used to apply angularly corrected patterns to line.  It
+* should only be used when LINE_PATTERN is also set.  The pattern will be
+* applied along the length of the line, instead of along the length of the
+* major axis.  This may result in the loss of fine details in the pattern, and
+* will take more time to draw the line in most cases.
+*/
+
+#define LINE_PATTERN            0x00000001
+#define LINE_PRECISE            0x00000002
+#define LINE_BACKGROUND         0x00000004
+
+struct ep93xx_line {
+    unsigned long flags;
+    unsigned long x1;
+    unsigned long y1;
+    unsigned long x2;
+    unsigned long y2;
+    unsigned long fgcolor;
+    unsigned long bgcolor;      // Only used if LINE_BACKGROUND is set
+    unsigned long pattern;      // Only used if LINE_PATTERN is set
+};
+
+#endif /* __EP93XXFB_H__ */
+
--- /dev/null
+++ b/drivers/video/ep93xxfb_mono.c
@@ -0,0 +1,1281 @@
+/*
+ *  drivers/video/ep93xxfb_mono.c -- grayscale on mono LCD driver for
+ *  Cirrus Logic EP93xx.
+ *
+ *  Copyright (C) 2007 Cirrus Logic
+ *
+ *  This file is subject to the terms and conditions of the GNU General Public
+ *  License. See the file COPYING in the main directory of this archive for
+ *  more details.
+ *
+ *  This driver works for the following two LCD:
+ *  SHARP LM121VB1T01   -   A dual scan 640x480 monochrome LCD.
+ *  HOSIDEN HLM6323     -   A single scan 320x240 monochrome LCD.
+ *
+ *  And support two gray modes:
+ *  8 levels of gray    -   Actually is 7 levels of gray. Two of the levels
+ *                          have the same gray.
+ *  16 levels of gray   -   Extending the gray levels by switching the LUT
+ *                          for each frame.
+ *
+ *  HW connection for SHARP LM121VB1T01:
+ *      P12 <------> LCD_U0
+ *      P8  <------> LCD_U1
+ *      P4  <------> LCD_U2
+ *      P0  <------> LCD_U3
+ *      P14 <------> LCD_L0
+ *      P10 <------> LCD_L1
+ *      P6  <------> LCD_L2
+ *      P2  <------> LCD_L3
+ *  HW connection for HOSIDEN HLM6323:
+ *      P12 <------> LCD_0
+ *      P8  <------> LCD_1
+ *      P4  <------> LCD_2
+ *      P0  <------> LCD_3
+ *
+ */
+
+#include <linux/version.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/reboot.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/delay.h>
+#include <linux/fb.h>
+#include <linux/init.h>
+#include <linux/ioport.h>
+#include <linux/interrupt.h>
+#include <linux/dma-mapping.h>
+#include <asm/io.h>
+#include <asm/uaccess.h>
+#include <mach/hardware.h>
+
+
+#include <linux/platform_device.h>
+
+#define CONFIG_EP93XX_SDCS0
+
+#undef DEBUG
+#ifdef DEBUG
+#define DPRINTK( fmt, arg... )  printk( fmt, ##arg )
+#else
+#define DPRINTK( fmt, arg... )
+#endif
+
+#define FBDEV_NAME "ep93xxfb"
+
+#define ep93xxfb_lock_outl(value, reg)              \
+{                                              \
+    outl(RASTER_SWLOCK_VALUE, RASTER_SWLOCK);  \
+    outl(value, reg);                          \
+    DPRINTK(#reg"=0x%08x\n", (unsigned int)(value));         \
+}
+
+#define ep93xxfb_outl(value, reg)              \
+{                                              \
+    outl(value, reg);                          \
+    DPRINTK(#reg"=0x%08x\n", (unsigned int)(value));         \
+}
+
+static unsigned int pseudo_palette[256];
+
+struct ep93xxfb_mono_videomodes
+{
+    const char *name;
+
+    unsigned long hres; 	// Horizontal Valid
+    unsigned long vres;		// Vertical Valid
+    unsigned int  freq;
+    unsigned int  dualscan;
+    unsigned int  bpp;
+    unsigned int  graylevel;
+
+    void (*configure)(unsigned char value);
+    void (*on)(unsigned char value);
+    void (*off)(unsigned char value);
+};
+
+struct ep93xxfb_mono_info
+{
+    dma_addr_t          fb_phys;
+    void	            *fb_log;
+    unsigned long       fb_size;
+    unsigned long		fb_actsize;
+
+    unsigned int        xres;
+    unsigned int        yres;
+
+    unsigned int        freq;
+    unsigned int        dualscan;
+    unsigned int        bpp;
+    unsigned int        graylevel;
+
+    void (*configure)(unsigned char value);
+    void (*on)(unsigned char value);
+    void (*off)(unsigned char value);
+};
+
+
+void LM121VB1T01_configure(unsigned char value);
+void HOSIDEN_HLM6323_configure(unsigned char value);
+
+static int vmode = 1;
+
+static struct ep93xxfb_mono_info epinfo;
+static struct ep93xxfb_mono_videomodes ep93xxfb_vmods[] =
+{
+    {
+        "SHARP-LM121VB1T01-8GRAY",
+        640, 480, 100,
+        1,  //dual scan
+        4,  //4bpp
+        8,  //8-level grayscale
+        LM121VB1T01_configure,
+        NULL,
+        NULL,
+    },
+    {
+        "SHARP-LM121VB1T01-16GRAY",
+        640, 480, 120,
+        1,  //dual scan
+        4,  //4bpp
+        16, //16-level grayscale
+        LM121VB1T01_configure,
+        NULL,
+        NULL,
+    },
+    {
+        "HOSIDEN HLM6323",
+        320, 240, 115,
+        0,  //single scan
+        4,  //4bpp
+        8,  //8-level grayscale
+        HOSIDEN_HLM6323_configure,
+        NULL,
+        NULL,
+    },
+    {
+        "HOSIDEN HLM6323",
+        320, 240, 115,
+        0,  //single scan
+        4,  //4bpp
+        16, //16-level grayscale
+        HOSIDEN_HLM6323_configure,
+        NULL,
+        NULL,
+    },
+};
+
+
+#define EP93XX_GS_OFFSET(lut, frame, pixel) ( (lut) + ( (pixel) << 2) + ((frame) << 5 ))
+
+static unsigned long DY_LUT[2][16];
+
+static unsigned long GSLUT[32] =
+{
+    0x00070000, 0x00070000, 0x00070000, 0x00070000,     /*0%*/
+    0x00078241, 0x00074182, 0x00071428, 0x00072814,     /*25%*/
+    0x00000412, 0x00000241, 0x00000124, 0x00000000,     /*33%*/
+    0x0007aa55, 0x000755aa, 0x000755aa, 0x0007aa55,     /*50%*/
+    0x00000bed, 0x00000dbe, 0x00000edb, 0x00000000,     /*66%*/
+    0x00077dbe, 0x0007be7d, 0x0007ebd7, 0x0007d7eb,     /*75%*/
+    0x0007ffff, 0x0007ffff, 0x0007ffff, 0x0007ffff,     /*100%*/
+    0x0007ffff, 0x0007ffff, 0x0007ffff, 0x0007ffff,
+};
+
+static void ep93xxfb_8gray_palette_init(void)
+{
+    unsigned int cont, i, n;
+    unsigned int frame, pixval, gslut;
+    cont = inl(LUTCONT);
+    for (i=0; i< 16; i++)
+    {
+        n = (i & 0xe) << 4;
+        outl( n, (COLOR_LUT+(i<<2)) );
+    }
+    for (pixval=0; pixval < 8; pixval++)
+    {
+        for (frame=0; frame < 4; frame++)
+        {
+            gslut = GSLUT[pixval*4 + frame];
+            outl(gslut,EP93XX_GS_OFFSET(GS_LUT,  frame, pixval));
+        }
+    }
+    outl( cont ^ LUTCONT_RAM1, LUTCONT );
+}
+
+static void ep93xxfb_16gray_palette_switch(int index)
+{
+    unsigned int cont, i, n;
+    cont = inl(LUTCONT);
+    n = index & 0x1;
+    for (i=0; i< 16; i++)
+    {
+        outl( DY_LUT[n][i], (COLOR_LUT+(i<<2)) );
+    }
+    outl( cont ^ LUTCONT_RAM1, LUTCONT );
+}
+
+static void ep93xxfb_16gray_palette_init(void)
+{
+    int i;
+    unsigned int cont;
+    unsigned int frame, pixval, gslut;
+    int split_table[16][2] =
+    {
+        {0,  0 },
+        {0,  2 },
+        {1,  1 },
+        {3,  0 },
+
+        {2,  2 },
+        {4,  0 },
+        {3,  2 },
+        {4,  2 },
+
+        {3,  3 },       //  {6,  0 },
+        {3,  4 },
+        {4,  4 },
+        {6,  2 },
+
+        {5,  5 },
+        {3,  6 },
+        {4,  6 },
+        {6,  6 },
+    };
+
+    cont = inl(LUTCONT);
+    for (i=0; i< 16; i++)
+    {
+        DY_LUT[0][i]=split_table[i][0] << 5;
+        DY_LUT[1][i]=split_table[i][1] << 5;
+
+        outl( DY_LUT[0][i], (COLOR_LUT+(i<<2)) );
+    }
+
+    for (pixval=0; pixval < 8; pixval++)
+    {
+        for (frame=0; frame < 4; frame++)
+        {
+            gslut = GSLUT[pixval*4 + frame];
+            outl(gslut,EP93XX_GS_OFFSET(GS_LUT,  frame, pixval));
+            outl(gslut,EP93XX_GS_OFFSET(GS_LUT2,  frame, pixval));
+            outl(gslut,EP93XX_GS_OFFSET(GS_LUT3,  frame, pixval));
+        }
+    }
+    outl( cont ^ LUTCONT_RAM1, LUTCONT );
+}
+
+static int ep93xxfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
+{
+    struct fb_var_screeninfo tmp_var;
+    DPRINTK("ep93xxfb_check_var - enter\n");
+
+    memcpy (&tmp_var, var, sizeof (tmp_var));
+
+    if (var->xres_virtual != var->xres)
+        var->xres_virtual = var->xres;
+    if (var->yres_virtual < var->yres)
+        var->yres_virtual = var->yres;
+
+    if (var->xoffset < 0)
+        var->xoffset = 0;
+    if (var->yoffset < 0)
+        var->yoffset = 0;
+
+    switch (tmp_var.bits_per_pixel)
+    {
+        case 4:
+            break;
+        default:
+            return -EINVAL;
+    }
+
+    DPRINTK("ep93xxfb_check_var - exit\n");
+    return 0;
+}
+
+static int ep93xxfb_set_par(struct fb_info *info)
+{
+    DPRINTK("ep93xxfb_set_par\n");
+    switch (info->var.bits_per_pixel) {
+        case 4:
+            info->fix.visual = FB_VISUAL_PSEUDOCOLOR;
+            break;
+
+        default:
+            return -EINVAL;
+    }
+
+    return 0;
+}
+
+
+static int ep93xxfb_blank(int blank_mode,struct fb_info *info)
+{
+    unsigned long attribs;
+    DPRINTK("ep93xxfb_blank - enter\n");
+    attribs = inl(VIDEOATTRIBS);
+
+    if (blank_mode) {
+        if (epinfo.off)
+            (epinfo.off)( 0 );
+
+        ep93xxfb_lock_outl(attribs & ~(VIDEOATTRIBS_DATAEN |
+                    VIDEOATTRIBS_SYNCEN | VIDEOATTRIBS_PCLKEN |
+                    VIDEOATTRIBS_EN), VIDEOATTRIBS);
+    }
+    else {
+
+        if (epinfo.configure)
+            (epinfo.configure)( (unsigned char) epinfo.graylevel );
+        if (epinfo.on)
+            (epinfo.on)( 0 );
+    }
+    return 0;
+}
+
+static void ep93xxfb_get_par(struct fb_info *info)
+{
+
+    DPRINTK("ep93xxfb_get_par - enter\n");
+
+    epinfo.configure = ep93xxfb_vmods[vmode].configure;
+    epinfo.on = ep93xxfb_vmods[vmode].on;
+    epinfo.off = ep93xxfb_vmods[vmode].off;
+
+    epinfo.freq = ep93xxfb_vmods[vmode].freq;
+    epinfo.dualscan = ep93xxfb_vmods[vmode].dualscan;
+    epinfo.bpp = ep93xxfb_vmods[vmode].bpp;
+    epinfo.graylevel = ep93xxfb_vmods[vmode].graylevel;
+
+    epinfo.xres = ep93xxfb_vmods[vmode].hres;
+    epinfo.yres = ep93xxfb_vmods[vmode].vres;
+
+}
+
+static int ep93xxfb_alloc_videomem(void)
+{
+    unsigned long adr,size,pgsize;
+    int order;
+
+    DPRINTK("ep93xxfb_alloc_videomem - enter \n");
+
+    epinfo.fb_log = NULL;
+    epinfo.fb_size = epinfo.xres*epinfo.yres*epinfo.bpp/8;
+    order = get_order( epinfo.fb_size );
+    epinfo.fb_log = (void*) __get_free_pages( GFP_KERNEL, order );
+
+    if (epinfo.fb_log) {
+        epinfo.fb_phys = __virt_to_phys((int) epinfo.fb_log );
+        adr = (unsigned long)epinfo.fb_log;
+        size = epinfo.fb_size;
+        pgsize = 1 << order;
+        do {
+            adr += pgsize;
+            SetPageReserved(virt_to_page(adr));
+        } while(size -= pgsize);
+    }
+    else
+        return -ENOMEM;
+
+    memset(epinfo.fb_log,0x00,epinfo.fb_size);
+
+    DPRINTK("   fb_log_addres = 0x%x\n",    (unsigned int)epinfo.fb_log);
+    DPRINTK("   fb_phys_address = 0x%x\n",  (unsigned int)epinfo.fb_phys);
+    DPRINTK("   fb_size = %lu\n",           (unsigned long)epinfo.fb_size);
+    DPRINTK("   fb_page_order = %d\n",      (unsigned int)order);
+    DPRINTK("ep93xxfb_alloc_videomem - exit \n");
+    return 0;
+}
+
+static void ep93xxfb_release_videomem(void)
+{
+    unsigned long adr,size,psize;
+    int order;
+
+    DPRINTK("ep93xxfb_release_videomem - enter \n");
+    if (epinfo.fb_log) {
+        order = get_order(epinfo.fb_size);
+        adr = (unsigned long)epinfo.fb_log;
+        size = epinfo.fb_size;
+        psize = 1 << order ;
+        do {
+            adr += psize;
+            ClearPageReserved(virt_to_page(adr));
+        } while(size -= psize);
+        free_pages((unsigned long)epinfo.fb_log, order );
+    }
+    DPRINTK("ep93xxfb_release_videomem - exit \n");
+}
+
+static void ep93xxfb_setinfo(struct fb_info *info)
+{
+
+    DPRINTK("ep93xxfb_setinfo - enter \n");
+    info->pseudo_palette = pseudo_palette;
+    info->var.xres = epinfo.xres;
+    info->var.yres = epinfo.yres;
+    info->var.xres_virtual = epinfo.xres;
+    info->var.yres_virtual = epinfo.yres;
+
+    info->var.bits_per_pixel = epinfo.bpp;
+    info->var.red.length = epinfo.bpp;
+    info->var.green.length = epinfo.bpp;
+    info->var.blue.length = epinfo.bpp;
+    info->fix.visual = FB_VISUAL_PSEUDOCOLOR;
+    info->var.red.offset = 0;
+    info->var.green.offset =0;
+    info->var.blue.offset = 0;
+
+    info->fix.smem_start = epinfo.fb_phys;
+    info->fix.smem_len = epinfo.fb_size;
+    info->fix.type = FB_TYPE_PACKED_PIXELS;
+    info->fix.line_length = (epinfo.xres * epinfo.bpp) / 8;
+    info->fix.accel = FB_ACCEL_NONE;
+    info->screen_base = epinfo.fb_log;
+    info->fix.ypanstep = 1;
+    info->fix.ywrapstep = 1;
+
+    DPRINTK("ep93xxfb_setinfo - exit \n");
+}
+
+static int ep93xxfb_config(struct fb_info *info)
+{
+    DPRINTK("ep93xxfb_config - enter\n");
+
+    ep93xxfb_get_par( info );
+    if( ep93xxfb_alloc_videomem() != 0 ) {
+        printk("Unable to allocate video memory\n");
+        return -ENOMEM;
+    }
+
+    /* set video memory parameters */
+    ep93xxfb_outl(epinfo.fb_phys, VIDSCRNPAGE);
+    if(epinfo.dualscan)
+    {
+        ep93xxfb_outl(epinfo.fb_phys + (epinfo.bpp*epinfo.xres*epinfo.yres/16)
+                , VIDSCRNHPG);
+    }
+
+    DPRINTK("   fb_phys = 0x%x\n",  inl(VIDSCRNPAGE) );
+    DPRINTK("   fb_phys_hpg = 0x%x\n",  inl(VIDSCRNHPG));
+
+    ep93xxfb_outl(epinfo.yres , SCRNLINES);
+    ep93xxfb_outl(((epinfo.xres * epinfo.bpp) / 32) - 1, LINELENGTH);
+    ep93xxfb_outl((epinfo.xres * epinfo.bpp) / 32, VLINESTEP);
+
+    if(epinfo.configure)
+        (epinfo.configure)( (unsigned char) epinfo.graylevel );
+
+    ep93xxfb_setinfo( info );
+
+
+    DPRINTK("ep93xxfb_config - exit\n");
+    return 0;
+}
+
+static unsigned long ep93xx_get_pll_frequency(unsigned long pll)
+{
+    unsigned long fb1, fb2, ipd, ps, freq;
+
+    if (pll == 1)
+        pll = inl(EP93XX_SYSCON_CLOCK_SET1);
+    else if (pll == 2)
+        pll = inl(EP93XX_SYSCON_CLOCK_SET2);
+    else
+        return 0;
+
+    ps = (pll & SYSCON_CLKSET1_PLL1_PS_MASK) >>	SYSCON_CLKSET1_PLL1_PS_SHIFT;
+    fb1 = ((pll & SYSCON_CLKSET1_PLL1_X1FBD1_MASK) >> SYSCON_CLKSET1_PLL1_X1FBD1_SHIFT);
+    fb2 = ((pll & SYSCON_CLKSET1_PLL1_X2FBD2_MASK) >> SYSCON_CLKSET1_PLL1_X2FBD2_SHIFT);
+    ipd = ((pll & SYSCON_CLKSET1_PLL1_X2IPD_MASK) >> SYSCON_CLKSET1_PLL1_X2IPD_SHIFT);
+
+    freq = (((0x00e10000 * (fb1+1)) / (ipd+1)) * (fb2+1)) >> ps;
+    return freq;
+}
+
+static int ep93xx_set_video_div(unsigned long freq)
+{
+    unsigned long pdiv = 0, div = 0, psel = 0, esel = 0;
+    unsigned long err, f, i, j, k;
+
+    err = -1;
+
+    for (i = 0; i < 3; i++) {
+        if (i == 0)
+            f = 14745600 * 2;
+        else if (i == 1)
+            f = ep93xx_get_pll_frequency(1) * 2;
+        else
+            f = ep93xx_get_pll_frequency(2) * 2;
+
+        for (j = 4; j <= 6; j++) {
+            k = f / (freq * j);
+            if (k < 2)
+                continue;
+
+            if (abs(((f / (j * k))) - freq ) < err ) {
+                pdiv = j - 3;
+                div = k;
+                psel = (i == 2) ? 1 : 0;
+                esel = (i == 0) ? 0 : 1;
+                err = (f / (j * k)) - freq;
+            }
+        }
+    }
+
+    if (err == -1)
+        return -1;
+
+    f = SYSCON_VIDDIV_VENA | (esel ? SYSCON_VIDDIV_ESEL : 0) |
+        (psel ? SYSCON_VIDDIV_PSEL : 0) |
+        (pdiv << SYSCON_VIDDIV_PDIV_SHIFT) |
+        (div << SYSCON_VIDDIV_VDIV_SHIFT);
+    outl(0xaa, EP93XX_SYSCON_SWLOCK);
+    outl(f, SYSCON_VIDDIV);
+
+    return freq + err;
+}
+
+static int interrupt_hooked = 0;
+static int vs_counter = 0;
+
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17)
+static irqreturn_t ep93xxfb_irq_handler(int i, void *blah)
+#else
+static irqreturn_t ep93xxfb_irq_handler(int i, void *blah, struct pt_regs *regs)
+#endif
+{
+
+    outl(RASTER_SWLOCK_VALUE, RASTER_SWLOCK);
+    outl(
+#ifdef CONFIG_EP93XX_SDCS0
+            (0 << VIDEOATTRIBS_SDSEL_SHIFT) |
+#endif
+#ifdef CONFIG_EP93XX_SDCS1
+            (1 << VIDEOATTRIBS_SDSEL_SHIFT) |
+#endif
+#ifdef CONFIG_EP93XX_SDCS2
+            (2 << VIDEOATTRIBS_SDSEL_SHIFT) |
+#endif
+#ifdef CONFIG_EP93XX_SDCS3
+            (3 << VIDEOATTRIBS_SDSEL_SHIFT) |
+#endif
+            VIDEOATTRIBS_VCPOL | VIDEOATTRIBS_HSPOL |
+            VIDEOATTRIBS_DATAEN | VIDEOATTRIBS_SYNCEN | VIDEOATTRIBS_INVCLK |
+            VIDEOATTRIBS_PCLKEN | VIDEOATTRIBS_EN | VIDEOATTRIBS_INTEN ,
+            VIDEOATTRIBS       );
+
+    ep93xxfb_16gray_palette_switch(vs_counter++);
+
+    return IRQ_HANDLED;
+}
+
+void LM121VB1T01_configure(unsigned char value)
+{
+
+    int n;
+    unsigned long attribs;
+    printk("LM121VB1T01_configure\n");
+
+    switch(value)
+    {
+        case 8:
+            ep93xxfb_8gray_palette_init();
+            break;
+        case 16:
+            ep93xxfb_16gray_palette_init();
+            break;
+        default:
+            return;
+    }
+
+    SysconSetLocked(EP93XX_SYSCON_DEVICE_CONFIG, (inl(EP93XX_SYSCON_DEVICE_CONFIG) & ~EP93XX_SYSCON_DEVICE_CONFIG_CRUNCH_ENABLE) | EP93XX_SYSCON_DEVCFG_RasOnP3);
+
+    ep93xx_set_video_div(epinfo.freq*240*1280);
+
+    ep93xxfb_lock_outl( 0x00000000   ,   VIDEOATTRIBS       );
+
+    n = 240;
+    ep93xxfb_lock_outl( n + 3  ,   VLINESTOTAL        );
+    ep93xxfb_lock_outl( ((n)<<16) + n+1   ,   VSYNCSTRTSTOP      );
+    ep93xxfb_lock_outl( ((2)<<16) + n+2   ,   VACTIVESTRTSTOP    );
+    ep93xxfb_lock_outl( ((3)<<16) + n+3   ,   VBLANKSTRTSTOP     );
+    ep93xxfb_lock_outl( ((n+3)<<16) + n+3    ,   VCLKSTRTSTOP       );
+
+    n = 1280;
+    ep93xxfb_lock_outl( n + 15  ,   HCLKSTOTAL         );
+    ep93xxfb_lock_outl( ((n+5)<<16) + n+ 14    ,   HSYNCSTRTSTOP      );
+    ep93xxfb_lock_outl( ((15)<<16) + n + 15   ,   HACTIVESTRTSTOP    );
+    ep93xxfb_lock_outl( ((n+15)<<16) + 15 ,   HBLANKSTRTSTOP       );
+    ep93xxfb_lock_outl( ((n)<<16) + n   ,   HCLKSTRTSTOP       );
+
+    ep93xxfb_lock_outl( 14   ,   LINECARRY          );
+
+    attribs = 0;
+
+#ifdef CONFIG_EP93XX_SDCS0
+    attribs |= 0 << VIDEOATTRIBS_SDSEL_SHIFT;
+#endif
+#ifdef CONFIG_EP93XX_SDCS1
+    attribs |= 1 << VIDEOATTRIBS_SDSEL_SHIFT;
+#endif
+#ifdef CONFIG_EP93XX_SDCS2
+    attribs |= 2 << VIDEOATTRIBS_SDSEL_SHIFT;
+#endif
+#ifdef CONFIG_EP93XX_SDCS3
+    attribs |= 3 << VIDEOATTRIBS_SDSEL_SHIFT;
+#endif
+
+    switch(value)
+    {
+        case 8:
+            ep93xxfb_lock_outl( PIXELMODE_DSCAN |
+                PIXELMODE_S_8PPC | PIXELMODE_P_4BPP |
+                PIXELMODE_C_GSLUT   ,   PIXELMODE          );
+
+            ep93xxfb_lock_outl(
+                    attribs | VIDEOATTRIBS_VCPOL | VIDEOATTRIBS_HSPOL |
+                    VIDEOATTRIBS_DATAEN | VIDEOATTRIBS_SYNCEN | VIDEOATTRIBS_INVCLK |
+                    VIDEOATTRIBS_PCLKEN | VIDEOATTRIBS_EN ,
+                    VIDEOATTRIBS       );
+            break;
+        case 16:
+            if(!interrupt_hooked)
+            {
+                request_irq(IRQ_EP93XX_VSYNC, ep93xxfb_irq_handler, IRQF_DISABLED, "lut switch interrupt", NULL);
+                interrupt_hooked = 1;
+            }
+            ep93xxfb_lock_outl( PIXELMODE_DSCAN |
+                PIXELMODE_S_8PPC | PIXELMODE_P_4BPP | PIXELMODE_C_GSLUT, PIXELMODE );
+
+            ep93xxfb_lock_outl(
+                    attribs | VIDEOATTRIBS_VCPOL | VIDEOATTRIBS_HSPOL |
+                    VIDEOATTRIBS_DATAEN | VIDEOATTRIBS_SYNCEN | VIDEOATTRIBS_INVCLK |
+                    VIDEOATTRIBS_PCLKEN | VIDEOATTRIBS_EN | VIDEOATTRIBS_INTEN,
+                    VIDEOATTRIBS       );
+            break;
+        default:
+            return;
+    }
+
+}
+
+void HOSIDEN_HLM6323_configure(unsigned char value)
+{
+    int n;
+    unsigned long attribs;
+
+    printk("HOSIDEN_HLM6323_configure\n");
+
+    switch(value)
+    {
+        case 8:
+            ep93xxfb_8gray_palette_init();
+            break;
+        case 16:
+            ep93xxfb_16gray_palette_init();
+            break;
+        default:
+            return;
+    }
+
+    SysconSetLocked(EP93XX_SYSCON_DEVICE_CONFIG, inl(EP93XX_SYSCON_DEVICE_CONFIG)  |EP93XX_SYSCON_DEVCFG_RasOnP3);
+
+    ep93xxfb_lock_outl( 0x00000000   ,   VIDEOATTRIBS       );
+
+    ep93xx_set_video_div(epinfo.freq*320*240);
+    mdelay(10);
+
+    n = 240;
+    ep93xxfb_lock_outl( n + 3 ,   VLINESTOTAL        );
+    ep93xxfb_lock_outl( ((n+1)<<16) + n +2   ,   VSYNCSTRTSTOP      );
+    ep93xxfb_lock_outl( ((3)<<16) + n +3 ,   VACTIVESTRTSTOP    );
+    ep93xxfb_lock_outl( ((3)<<16) + n +3 ,   VBLANKSTRTSTOP     );
+    ep93xxfb_lock_outl( ((n+3)<<16) + n +3,   VCLKSTRTSTOP       );
+
+    n = 320;
+    ep93xxfb_lock_outl( n + 3,   HCLKSTOTAL         );
+    ep93xxfb_lock_outl( ((n+1)<<16) + n+2    ,   HSYNCSTRTSTOP      );
+    ep93xxfb_lock_outl( ((3)<<16) + n+3  ,   HACTIVESTRTSTOP    );
+    ep93xxfb_lock_outl( ((3)<<16) + n+3 ,   HBLANKSTRTSTOP       );
+    ep93xxfb_lock_outl( ((n+3)<<16) + n+3  ,   HCLKSTRTSTOP       );
+
+    ep93xxfb_lock_outl( 3   ,   LINECARRY          );
+
+    attribs = 0;
+
+#ifdef CONFIG_EP93XX_SDCS0
+    attribs |= 0 << VIDEOATTRIBS_SDSEL_SHIFT;
+#endif
+#ifdef CONFIG_EP93XX_SDCS1
+    attribs |= 1 << VIDEOATTRIBS_SDSEL_SHIFT;
+#endif
+#ifdef CONFIG_EP93XX_SDCS2
+    attribs |= 2 << VIDEOATTRIBS_SDSEL_SHIFT;
+#endif
+#ifdef CONFIG_EP93XX_SDCS3
+    attribs |= 3 << VIDEOATTRIBS_SDSEL_SHIFT;
+#endif
+
+    switch(value)
+    {
+        case 8:
+            ep93xxfb_lock_outl(
+                PIXELMODE_S_4PPC | PIXELMODE_P_4BPP | PIXELMODE_C_GSLUT,   PIXELMODE );
+            ep93xxfb_lock_outl(
+                    attribs | VIDEOATTRIBS_VCPOL | VIDEOATTRIBS_HSPOL |
+                    VIDEOATTRIBS_DATAEN | VIDEOATTRIBS_SYNCEN | VIDEOATTRIBS_INVCLK |
+                    VIDEOATTRIBS_PCLKEN | VIDEOATTRIBS_EN ,
+                    VIDEOATTRIBS       );
+            break;
+        case 16:
+            ep93xxfb_lock_outl(
+                PIXELMODE_S_4PPC | PIXELMODE_P_4BPP | PIXELMODE_C_GSLUT,   PIXELMODE );
+            if(!interrupt_hooked)
+            {
+                request_irq(IRQ_EP93XX_VSYNC, ep93xxfb_irq_handler, IRQF_DISABLED, "lut switch interrupt", NULL);
+                interrupt_hooked = 1;
+            }
+            ep93xxfb_lock_outl(
+                    attribs | VIDEOATTRIBS_VCPOL | VIDEOATTRIBS_HSPOL |
+                    VIDEOATTRIBS_DATAEN | VIDEOATTRIBS_SYNCEN | VIDEOATTRIBS_INVCLK |
+                    VIDEOATTRIBS_PCLKEN | VIDEOATTRIBS_EN | VIDEOATTRIBS_INTEN,
+                    VIDEOATTRIBS       );
+            break;
+        default:
+            return;
+    }
+}
+
+#define FB_WRITEL fb_writel
+#define FB_READL  fb_readl
+#define LEFT_POS(bpp)          (0)
+#define SHIFT_HIGH(val, bits)  ((val) << (bits))
+#define SHIFT_LOW(val, bits)   ((val) >> (bits))
+static inline void color_imageblit(const struct fb_image *image,
+        struct fb_info *p, u8 *dst1,
+        u32 start_index,
+        u32 pitch_index)
+{
+    /* Draw the penguin */
+    u32 *dst, *dst2;
+    u32 color = 0, val, shift;
+    int i, n, bpp = p->var.bits_per_pixel;
+    u32 null_bits = 32 - bpp;
+    u32 *palette = (u32 *) p->pseudo_palette;
+    const u8 *src = image->data;
+
+    dst2 = (u32 *) dst1;
+    for (i = image->height; i--; ) {
+        n = image->width;
+        dst = (u32 *) dst1;
+        shift = 0;
+        val = 0;
+
+        if (start_index) {
+            u32 start_mask = ~(SHIFT_HIGH(~(u32)0, start_index));
+            val = FB_READL(dst) & start_mask;
+            shift = start_index;
+        }
+        while (n--) {
+            if (p->fix.visual == FB_VISUAL_TRUECOLOR ||
+                    p->fix.visual == FB_VISUAL_DIRECTCOLOR )
+                color = palette[*src];
+            else
+                color = *src;
+            color <<= LEFT_POS(bpp);
+            val |= SHIFT_HIGH(color, shift);
+            if (shift >= null_bits) {
+                FB_WRITEL(val, dst++);
+
+                val = (shift == null_bits) ? 0 :
+                    SHIFT_LOW(color, 32 - shift);
+            }
+            shift += bpp;
+            shift &= (32 - 1);
+            src++;
+        }
+        if (shift) {
+            u32 end_mask = SHIFT_HIGH(~(u32)0, shift);
+
+            FB_WRITEL((FB_READL(dst) & end_mask) | val, dst);
+        }
+        dst1 += p->fix.line_length;
+        if (pitch_index) {
+            dst2 += p->fix.line_length;
+            dst1 = (u8 *)((long __force)dst2 & ~(sizeof(u32) - 1));
+
+            start_index += pitch_index;
+            start_index &= 32 - 1;
+        }
+    }
+}
+
+static const int reversebit[]=
+{
+    7, 6, 5, 4, 3, 2, 1, 0,
+    15,14,13,12,11,10, 9, 8,
+    23,22,21,20,19,18,17,16,
+    31,30,29,28,27,26,25,24,
+};
+static inline void slow_imageblit(const struct fb_image *image, struct fb_info *p,
+        u8 *dst1, u32 fgcolor,
+        u32 bgcolor,
+        u32 start_index,
+        u32 pitch_index)
+{
+    u32 shift, color = 0, bpp = p->var.bits_per_pixel;
+    u32 *dst, *dst2;
+    u32 val, pitch = p->fix.line_length;
+    u32 null_bits = 32 - bpp;
+    u32 spitch = (image->width+7)/8;
+    const u8 *src = image->data, *s;
+    u32 i, j, l;
+
+    dst2 = (u32 *) dst1;
+    fgcolor <<= LEFT_POS(bpp);
+    bgcolor <<= LEFT_POS(bpp);
+    for (i = image->height; i--; ) {
+        shift = val = 0;
+        l = 8;
+        j = image->width;
+        dst = (u32 *) dst1;
+        s = src;
+
+        /* write leading bits */
+        if (start_index) {
+            u32 start_mask = ~(SHIFT_HIGH(~(u32)0,start_index));
+            val = FB_READL(dst) & start_mask;
+            shift = start_index;
+        }
+
+        while (j--) {
+            l--;
+            color = (*s & (1 << l)) ? fgcolor : bgcolor;
+            val |= SHIFT_HIGH(color, reversebit[shift]);
+            /* Did the bitshift spill bits to the next long? */
+            if (shift >= null_bits) {
+                FB_WRITEL(val, dst++);
+                val = (shift == null_bits) ? 0 :
+                    SHIFT_LOW(color, 32 - reversebit[shift]);
+            }
+            shift += bpp;
+            shift &= (32 - 1);
+            if (!l) { l = 8; s++; };
+        }
+
+        /* write trailing bits */
+        if (shift) {
+            u32 end_mask = SHIFT_HIGH(~(u32)0, shift);
+
+            FB_WRITEL((FB_READL(dst) & end_mask) | val, dst);
+        }
+
+        dst1 += pitch;
+        src += spitch;
+        if (pitch_index) {
+            dst2 += pitch;
+            dst1 = (u8 *)((long __force)dst2 & ~(sizeof(u32) - 1));
+            start_index += pitch_index;
+            start_index &= 32 - 1;
+        }
+
+    }
+}
+
+static void ep93xx_imageblit(struct fb_info *p, const struct fb_image *image)
+{
+    u32 fgcolor, bgcolor, start_index, bitstart, pitch_index = 0;
+    u32 bpl = sizeof(u32), bpp = p->var.bits_per_pixel;
+    u32 dx = image->dx, dy = image->dy;
+    u8 *dst1;
+
+    if (p->state != FBINFO_STATE_RUNNING)
+        return;
+
+    bitstart = (dy * p->fix.line_length * 8) + (dx * bpp);
+    start_index = bitstart & (32 - 1);
+    pitch_index = (p->fix.line_length & (bpl - 1)) * 8;
+
+    bitstart /= 8;
+    bitstart &= ~(bpl - 1);
+    dst1 = p->screen_base + bitstart;
+
+    if (p->fbops->fb_sync)
+        p->fbops->fb_sync(p);
+
+    if (image->depth == 1) {
+        if (p->fix.visual == FB_VISUAL_TRUECOLOR ||
+                p->fix.visual == FB_VISUAL_DIRECTCOLOR) {
+            fgcolor = ((u32*)(p->pseudo_palette))[image->fg_color];
+            bgcolor = ((u32*)(p->pseudo_palette))[image->bg_color];
+        } else {
+            fgcolor = image->fg_color;
+            bgcolor = image->bg_color;
+        }
+        slow_imageblit(image, p, dst1, fgcolor, bgcolor,
+                start_index, pitch_index);
+    } else
+        color_imageblit(image, p, dst1, start_index, pitch_index);
+}
+
+
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,8)
+
+int ep93xxfb_ioctl(struct fb_info *info,unsigned int cmd, unsigned long arg)
+{
+    return 0;
+}
+
+static int ep93xxfb_mmap(struct fb_info *info,struct vm_area_struct *vma)
+{
+    unsigned long off, start, len;
+
+    DPRINTK("ep93xxfb_mmap - enter\n");
+
+    off = vma->vm_pgoff << PAGE_SHIFT;
+    start = info->fix.smem_start;
+    len = PAGE_ALIGN(start & ~PAGE_MASK) + info->fix.smem_len;
+    start &= PAGE_MASK;
+    if ((vma->vm_end - vma->vm_start + off) > len)
+        return -EINVAL;
+
+    off += start;
+    vma->vm_pgoff = off >> PAGE_SHIFT;
+
+    vma->vm_flags |= VM_IO;
+    vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot);
+
+    if (io_remap_pfn_range(vma, vma->vm_start, off >> PAGE_SHIFT,
+                vma->vm_end - vma->vm_start, vma->vm_page_prot)) {
+        DPRINTK("ep93xxfb_mmap error\n");
+        return -EAGAIN;
+    }
+
+    DPRINTK("ep93xxfb_mmap - exit\n");
+    return 0;
+}
+
+
+static struct fb_ops ep93xxfb_ops = {
+    .owner          = THIS_MODULE,
+    .fb_check_var   = ep93xxfb_check_var,
+    .fb_set_par     = ep93xxfb_set_par,
+    .fb_blank       = ep93xxfb_blank,
+    .fb_fillrect    = cfb_fillrect,
+    .fb_copyarea    = cfb_copyarea,
+    //    .fb_imageblit   = cfb_imageblit,
+    .fb_imageblit   = ep93xx_imageblit,
+    .fb_ioctl       = ep93xxfb_ioctl,
+    .fb_mmap        = ep93xxfb_mmap,
+};
+
+
+static struct resource ep93xxfb_raster_resources = {
+    .start          = EP93XX_RASTER_PHYS_BASE,
+    .end            = EP93XX_RASTER_PHYS_BASE + 0x1ffff,
+    .flags          = IORESOURCE_MEM,
+};
+
+
+static int __init ep93xxfb_probe(struct platform_device *device)
+{
+    struct fb_info *info = NULL;
+    struct resource *res = NULL;
+    int ret = 0;
+    int arb = 0;
+
+    DPRINTK("ep93xxfb_probe - enter \n");
+
+    if(!device) {
+        printk("error : to_platform_device\n");
+        return -ENODEV;
+    }
+    res = platform_get_resource( device, IORESOURCE_MEM, 0);
+    if(!res) {
+        printk("error : platform_get_resource \n");
+        return -ENODEV;
+    }
+    if (!request_mem_region(res->start,res->end - res->start + 1, FBDEV_NAME ))
+        return -EBUSY;
+
+    info = framebuffer_alloc(sizeof(u32) * 256, &device->dev);
+
+    if(!info) {
+        printk("Unable to allocate memory for frame buffer\n");
+        return -ENOMEM;
+    }
+
+    info->flags = FBINFO_DEFAULT;
+    strncpy(info->fix.id, FBDEV_NAME, sizeof(info->fix.id));
+    info->fix.mmio_start = res->start;
+    info->fix.mmio_len = res->end - res->start + 1;
+    info->fbops = &ep93xxfb_ops;
+    info->pseudo_palette = info->par;
+    info->state = FBINFO_STATE_RUNNING;
+
+    printk("mmio_start = 0x%08x\n", res->start);
+    printk("mmio_len = 0x%08x\n", res->end - res->start + 1);
+
+    if (fb_alloc_cmap(&info->cmap, 256, 0) < 0) {
+        ret = -ENOMEM;
+        goto fbuff;
+    }
+
+    if ((ret = ep93xxfb_config(info)) < 0)
+        goto clmap;
+
+    if (register_framebuffer(info) < 0) {
+        printk(KERN_ERR "Unable to register ep93xxfb frame buffer\n");
+        ret = -EINVAL;
+        goto clmap;
+    }
+    platform_set_drvdata(device, info);
+    printk(KERN_INFO "fb%d: EP93xx frame buffer at %dx%dx%dbpp\n", info->node,
+            info->var.xres, info->var.yres, info->var.bits_per_pixel);
+
+    /*change the raster arb to the highest one--Bo*/
+    arb = inl(EP93XX_SYSCON_BMAR);
+    arb = (arb & 0x3f8) | 0x01;
+    ep93xxfb_outl(arb,EP93XX_SYSCON_BMAR);
+
+    DPRINTK("ep93xxfb_probe - exit \n");
+    return 0;
+
+clmap:
+    fb_dealloc_cmap(&info->cmap);
+
+fbuff:
+    framebuffer_release(info);
+    return ret;
+}
+
+static int ep93xxfb_remove(struct platform_device *device)
+{
+    struct resource *res;
+    struct fb_info *info;
+
+    DPRINTK("ep93xxfb_remove - enter \n");
+
+    info = platform_get_drvdata(device);
+
+    ep93xxfb_release_videomem();
+
+    res = platform_get_resource( device, IORESOURCE_MEM, 0);
+    release_mem_region(res->start, res->end - res->start + 1);
+
+    platform_set_drvdata(device, NULL);
+    unregister_framebuffer(info);
+
+    fb_dealloc_cmap(&info->cmap);
+    framebuffer_release(info);
+
+    ep93xxfb_blank( 1, info );
+
+    DPRINTK("ep93xxfb_remove - exit \n");
+    return 0;
+}
+
+static void ep93xxfb_platform_release(struct device *device)
+{
+    DPRINTK("ep93xxfb_platform_release - enter\n");
+}
+
+
+static struct platform_driver ep93xxfb_driver = {
+    .probe  = ep93xxfb_probe,
+    .remove = ep93xxfb_remove,
+    .driver = {
+        .name   = FBDEV_NAME,
+    },
+};
+
+static struct platform_device ep93xxfb_device = {
+    .name      = FBDEV_NAME,
+    .id        = -1,
+    .dev    = {
+        .release = ep93xxfb_platform_release,
+    },
+    .num_resources  = 1,
+    .resource       = &ep93xxfb_raster_resources,
+};
+
+int __init ep93xxfb_init(void)
+{
+    int ret = 0;
+
+    DPRINTK("ep93xxfb_init - enter\n");
+
+    ret = platform_driver_register(&ep93xxfb_driver);
+
+    if (!ret) {
+        ret = platform_device_register(&ep93xxfb_device);
+        if (ret)
+            platform_driver_unregister(&ep93xxfb_driver);
+    }
+    DPRINTK("ep93xxfb_init - exit\n");
+    return ret;
+}
+
+static void __exit ep93xxfb_exit(void)
+{
+    DPRINTK("ep93xxfb_exit - enter\n");
+    platform_driver_unregister(&ep93xxfb_driver);
+    platform_device_unregister(&ep93xxfb_device);
+    DPRINTK("ep93xxfb_exit - exit\n");
+}
+
+#else  //  LINUX_VERSION_CODE
+
+
+int ep93xxfb_setcolreg(unsigned regno, unsigned red, unsigned green,
+        unsigned blue, unsigned transp,
+        struct fb_info *info)
+{
+    return 0;
+}
+static struct fb_ops ep93xxfb_ops = {
+    .owner          = THIS_MODULE,
+    .fb_setcolreg   = ep93xxfb_setcolreg,
+    .fb_check_var   = ep93xxfb_check_var,
+    .fb_set_par     = ep93xxfb_set_par,
+    .fb_blank       = ep93xxfb_blank,
+    .fb_fillrect    = cfb_fillrect,
+    .fb_copyarea    = cfb_copyarea,
+    .fb_imageblit   = ep93xx_imageblit,
+    .fb_cursor	= soft_cursor,
+};
+
+static int __init ep93xxfb_probe(struct device *device)
+{
+    struct platform_device *pdev = to_platform_device(device);
+    struct fb_info *info = NULL;
+    struct resource *res = NULL;
+    int ret = 0;
+    int arb = 0;
+
+    DPRINTK("ep93xxfb_probe - enter \n");
+
+
+    if(!device) {
+        printk("error : to_platform_device\n");
+        return -ENODEV;
+    }
+    res = platform_get_resource( pdev, IORESOURCE_MEM, 0);
+    if(!res) {
+        printk("error : platform_get_resource \n");
+        return -ENODEV;
+    }
+    if (!request_mem_region(res->start,res->end - res->start + 1, FBDEV_NAME ))
+        return -EBUSY;
+
+    info = framebuffer_alloc(sizeof(u32) * 256, &pdev->dev);
+
+    if(!info) {
+        printk("Unable to allocate memory for frame buffer\n");
+        return -ENOMEM;
+    }
+
+    info->flags = FBINFO_DEFAULT;
+    strncpy(info->fix.id, FBDEV_NAME, sizeof(info->fix.id));
+    info->fix.mmio_start = res->start;
+    info->fix.mmio_len = res->end - res->start + 1;
+    info->fbops = &ep93xxfb_ops;
+    info->pseudo_palette = info->par;
+    info->state = FBINFO_STATE_RUNNING;
+
+    if (fb_alloc_cmap(&info->cmap, 256, 0) < 0) {
+        ret = -ENOMEM;
+        goto fbuff;
+    }
+
+    if ((ret = ep93xxfb_config(info)) < 0)
+        goto clmap;
+
+    if (register_framebuffer(info) < 0) {
+        printk(KERN_ERR "Unable to register ep93xxfb frame buffer\n");
+        ret = -EINVAL;
+        goto clmap;
+    }
+    dev_set_drvdata(device, info);
+    printk(KERN_INFO "fb%d: EP93xx frame buffer at %dx%dx%dbpp\n", info->node,
+            info->var.xres, info->var.yres, info->var.bits_per_pixel);
+
+    /*change the raster arb to the highest one--Bo*/
+    arb = inl(EP93XX_SYSCON_BMAR);
+    arb = (arb & 0x3f8) | 0x01;
+    ep93xxfb_outl(arb,EP93XX_SYSCON_BMAR);
+
+    DPRINTK("ep93xxfb_probe - exit \n");
+    return 0;
+
+clmap:
+    fb_dealloc_cmap(&info->cmap);
+
+fbuff:
+    framebuffer_release(info);
+    return ret;
+}
+
+static int ep93xxfb_remove(struct device *device)
+{
+    struct platform_device *pdev = to_platform_device(device);
+    struct resource *res;
+    struct fb_info *info;
+
+    DPRINTK("ep93xxfb_remove - enter \n");
+
+    info = dev_get_drvdata(device);
+
+    ep93xxfb_release_videomem();
+
+    res = platform_get_resource( pdev, IORESOURCE_MEM, 0);
+    release_mem_region(res->start, res->end - res->start + 1);
+
+    dev_set_drvdata(device, NULL);
+    unregister_framebuffer(info);
+
+    fb_dealloc_cmap(&info->cmap);
+    framebuffer_release(info);
+
+    ep93xxfb_blank( 1, info );
+
+    DPRINTK("ep93xxfb_remove - exit \n");
+    return 0;
+}
+static struct device_driver ep93xxfb_driver = {
+    .name		= FBDEV_NAME,
+    .bus		= &platform_bus_type,
+    .probe		= ep93xxfb_probe,
+    .remove		= ep93xxfb_remove,
+};
+int __init ep93xxfb_init(void)
+{
+    DPRINTK("ep93xxfb_init\n");
+    return driver_register(&ep93xxfb_driver);
+}
+
+static void __exit ep93xxfb_exit(void)
+{
+    DPRINTK("ep93xxfb_exit\n");
+    return driver_unregister(&ep93xxfb_driver);
+}
+
+int __init ep93xxfb_setup(char *options)
+{
+    DPRINTK("ep93xxfb_setup\n");
+    return 0;
+}
+
+#endif  //  LINUX_VERSION_CODE
+
+
+module_init(ep93xxfb_init);
+module_exit(ep93xxfb_exit);
+MODULE_AUTHOR("John Zheng <yujiang.zheng@cirrus.com>");
+MODULE_LICENSE("GPL");
+
--- a/arch/arm/mach-ep93xx/include/mach/hardware.h
+++ b/arch/arm/mach-ep93xx/include/mach/hardware.h
@@ -7,6 +7,7 @@
 #include "ep93xx-regs.h"
 
 #define pcibios_assign_all_busses()	0
+#include "regs_raster.h"
 #include "regs_touch.h"
 
 #include "platform.h"
--- a/arch/arm/mach-ep93xx/include/mach/irqs.h
+++ b/arch/arm/mach-ep93xx/include/mach/irqs.h
@@ -34,7 +34,8 @@
 #define IRQ_EP93XX_UART3TX		28
 #define IRQ_EP93XX_KEY			29
 #define IRQ_EP93XX_TOUCH		30
-#define EP93XX_VIC1_VALID_IRQ_MASK	0x7ffffffc
+#define IRQ_EP93XX_GRAPHICS		31
+#define EP93XX_VIC1_VALID_IRQ_MASK	0xfffffffc
 
 #define IRQ_EP93XX_EXT0			32
 #define IRQ_EP93XX_EXT1			33
--- /dev/null
+++ b/arch/arm/mach-ep93xx/include/mach/regs_raster.h
@@ -0,0 +1,347 @@
+/*=============================================================================
+ *
+ *  FILE:       	regs_raster.h
+ *
+ *  DESCRIPTION:    ep93xx Raster Engine Register Definition
+ *
+ *  Copyright Cirrus Logic, 2001-2003
+ *
+ * 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
+ *
+ *=============================================================================
+ */
+#ifndef _REGS_RASTER_H_
+#define _REGS_RASTER_H_
+
+//-----------------------------------------------------------------------------
+// VLINESTOTAL Register Definitions
+//-----------------------------------------------------------------------------
+#define VLINESTOTAL_MASK            0x000007ff
+
+//-----------------------------------------------------------------------------
+// VSYNCSTRTSTOP Register Definitions
+//-----------------------------------------------------------------------------
+#define VSYNCSTRTSTOP_STRT_MASK     0x07ff0000
+#define VSYNCSTRTSTOP_STRT_SHIFT    0
+#define VSYNCSTRTSTOP_STOP_MASK     0x000007ff
+#define VSYNCSTRTSTOP_STOP_SHIFT    16
+
+//-----------------------------------------------------------------------------
+// VACTIVESTRTSTOP Register Definitions
+//-----------------------------------------------------------------------------
+#define VACTIVESTRTSTOP_STRT_MASK   0x07ff0000
+#define VACTIVESTRTSTOP_STRT_SHIFT  0
+#define VACTIVESTRTSTOP_STOP_MASK   0x000007ff
+#define VACTIVESTRTSTOP_STOP_SHIFT  16
+
+//-----------------------------------------------------------------------------
+// VCLKSTRTSTOP Register Definitions
+//-----------------------------------------------------------------------------
+#define VCLKSTRTSTOP_STRT_MASK      0x07ff0000
+#define VCLKSTRTSTOP_STRT_SHIFT     0
+#define VCLKSTRTSTOP_STOP_MASK      0x000007ff
+#define VCLKSTRTSTOP_STOP_SHIFT     16
+
+//-----------------------------------------------------------------------------
+// VBLANKSTRTSTOP Register Definitions
+//-----------------------------------------------------------------------------
+#define VBLANKSTRTSTOP_STRT_MASK  0x07ff0000
+#define VBLANKSTRTSTOP_STRT_SHIFT 0
+#define VBLANKSTRTSTOP_STOP_MASK  0x000007ff
+#define VBLANKSTRTSTOP_STOP_SHIFT 16
+
+//-----------------------------------------------------------------------------
+// HSYNCSTRTSTOP Register Definitions
+//-----------------------------------------------------------------------------
+#define HSYNCSTRTSTOP_STRT_MASK      0x07ff0000
+#define HSYNCSTRTSTOP_STRT_SHIFT     0
+#define HSYNCSTRTSTOP_STOP_MASK      0x000007ff
+#define HSYNCSTRTSTOP_STOP_SHIFT     16
+
+//-----------------------------------------------------------------------------
+// HACTIVESTRTSTOP Register Definitions
+//-----------------------------------------------------------------------------
+#define HACTIVESTRTSTOP_STRT_MASK    0x07ff0000
+#define HACTIVESTRTSTOP_STRT_SHIFT   0
+#define HACTIVESTRTSTOP_STOP_MASK    0x000007ff
+#define HACTIVESTRTSTOP_STOP_SHIFT   16
+
+//-----------------------------------------------------------------------------
+// HCLKSTRTSTOP Register Definitions
+//-----------------------------------------------------------------------------
+#define HCLKSTRTSTOP_STRT_MASK      0x07ff0000
+#define HCLKSTRTSTOP_STRT_SHIFT     0
+#define HCLKSTRTSTOP_STOP_MASK      0x000007ff
+#define HCLKSTRTSTOP_STOP_SHIFT     16
+
+//-----------------------------------------------------------------------------
+// BRIGHTNESS Register Definitions
+//-----------------------------------------------------------------------------
+#define BRIGHTNESS_MASK             0x0000ffff
+#define BRIGHTNESS_CNT_MASK         0x000000ff
+#define BRIGHTNESS_CNT_SHIFT        0
+#define BRIGHTNESS_CMP_MASK         0x0000ff00
+#define BRIGHTNESS_CMP_SHIFT        8
+
+//-----------------------------------------------------------------------------
+// VIDEOATTRIBS Register Definitions
+//-----------------------------------------------------------------------------
+#define VIDEOATTRIBS_MASK           0x001fffff
+#define VIDEOATTRIBS_EN             0x00000001
+#define VIDEOATTRIBS_PCLKEN         0x00000002
+#define VIDEOATTRIBS_SYNCEN         0x00000004
+#define VIDEOATTRIBS_DATAEN         0x00000008
+#define VIDEOATTRIBS_CSYNC          0x00000010
+#define VIDEOATTRIBS_VCPOL          0x00000020
+#define VIDEOATTRIBS_HSPOL          0x00000040
+#define VIDEOATTRIBS_BLKPOL         0x00000080
+#define VIDEOATTRIBS_INVCLK         0x00000100
+#define VIDEOATTRIBS_ACEN           0x00000200
+#define VIDEOATTRIBS_LCDEN          0x00000400
+#define VIDEOATTRIBS_CCIREN         0x00001000
+#define VIDEOATTRIBS_PIFEN          0x00002000
+#define VIDEOATTRIBS_INTEN          0x00004000
+#define VIDEOATTRIBS_INT            0x00008000
+#define VIDEOATTRIBS_INTRLC         0x00010000
+#define VIDEOATTRIBS_EQUSER         0x00020000
+#define VIDEOATTRIBS_DHORZ          0x00040000
+#define VIDEOATTRIBS_DVERT          0x00080000
+#define VIDEOATTRIBS_BKPXD          0x00100000
+
+#define VIDEOATTRIBS_SDSEL_MASK     0x00600000
+#define VIDEOATTRIBS_SDSEL_SHIFT    21
+
+//-----------------------------------------------------------------------------
+// HBLANKSTRTSTOP Register Definitions
+//-----------------------------------------------------------------------------
+#define HBLANKSTRTSTOP_STRT_MASK    0x07ff0000
+#define HBLANKSTRTSTOP_STRT_SHIFT   0
+#define HBLANKSTRTSTOP_STOP_MASK    0x000007ff
+#define HBLANKSTRTSTOP_STOP_SHIFT   16
+
+//-----------------------------------------------------------------------------
+// LINECARRY Register Definitions
+//-----------------------------------------------------------------------------
+#define LINECARRY_LCARY_MASK        0x000007ff
+#define LINECARRY_LCARY_SHIFT       0
+
+//-----------------------------------------------------------------------------
+// BLINKRATE Register Definitons
+//-----------------------------------------------------------------------------
+#define BLINKRATE_MASK              0x000000ff
+
+//-----------------------------------------------------------------------------
+// BLINKMASK Register Definitons
+//-----------------------------------------------------------------------------
+#define BLINKMASK_MASK              0x00ffffff
+
+//-----------------------------------------------------------------------------
+// VIDSCRNPAGE Register Definitons
+//-----------------------------------------------------------------------------
+#define VIDSCRNPAGE_PAGE_MASK       0x0ffffffc
+
+//-----------------------------------------------------------------------------
+// VIDSCRNHPG Register Definitons
+//-----------------------------------------------------------------------------
+#define VIDSCRNHPG_MASK             0x0ffffffc
+
+//-----------------------------------------------------------------------------
+// SCRNLINES Register Definitons
+//-----------------------------------------------------------------------------
+#define SCRNLINES_MASK              0x000007ff
+
+//-----------------------------------------------------------------------------
+// LINELENGTH Register Definitons
+//-----------------------------------------------------------------------------
+#define LINELENGTH_MASK             0x000007ff
+
+//-----------------------------------------------------------------------------
+// VLINESTEP Register Definitons
+//-----------------------------------------------------------------------------
+#define VLINESTEP_MASK              0x00000fff
+
+//-----------------------------------------------------------------------------
+// RASTER_SWLOCK Register Definitons
+//-----------------------------------------------------------------------------
+#define RASTER_SWLOCK_MASK_WR      0xff
+#define RASTER_SWLOCK_MASK_R       0x1
+#define RASTER_SWLOCK_VALUE        0xaa
+
+//-----------------------------------------------------------------------------
+// LUTCONT Register Definitions
+//-----------------------------------------------------------------------------
+#define LUTCONT_MASK                0x00000003
+#define LUTCONT_SWTCH               0x00000001
+#define LUTCONT_STAT                0x00000002
+#define LUTCONT_RAM0                0
+#define LUTCONT_RAM1                1
+
+//-----------------------------------------------------------------------------
+// CURSORBLINK1 Register Definitions
+//-----------------------------------------------------------------------------
+#define CURSORBLINK1_MASK           0x00ffffff
+//-----------------------------------------------------------------------------
+// CURSORBLINK2 Register Definitions
+//-----------------------------------------------------------------------------
+#define CURSORBLINK2_MASK           0x00ffffff
+
+//-----------------------------------------------------------------------------
+// CURSORBLINK Register Definitions
+//-----------------------------------------------------------------------------
+#define CURSORBLINK_MASK            0x000001ff
+#define CURSORBLINK_RATE_MASK       0x000000ff
+#define CURSORBLINK_RATE_SHIFT      0
+#define CURSORBLINK_EN              0x00000100
+
+//-----------------------------------------------------------------------------
+// BLINKPATRN Register Definitions
+//-----------------------------------------------------------------------------
+#define BLINKPATRN_MASK             0x00ffffff
+
+//-----------------------------------------------------------------------------
+// PATRNMASK Register Definitions
+//-----------------------------------------------------------------------------
+#define PATRNMASK_MASK              0x00ffffff
+
+//-----------------------------------------------------------------------------
+// BG_OFFSET Register Definitions
+//-----------------------------------------------------------------------------
+#define BG_OFFSET_MASK              0x00ffffff
+
+//-----------------------------------------------------------------------------
+// PIXELMODE Register Definitions
+//-----------------------------------------------------------------------------
+#define PIXELMODE_P_MASK            0x00000007
+#define PIXELMODE_P_MUX_DISABLE     0x00000000
+#define PIXELMODE_P_4BPP            0x00000001
+#define PIXELMODE_P_8BPP            0x00000002
+#define PIXELMODE_P_16BPP           0x00000004
+#define PIXELMODE_P_24BPP           0x00000006
+#define PIXELMODE_P_32BPP           0x00000007
+
+#define PIXELMODE_S_MASK            0x00000038
+#define PIXELMODE_S_1PPC            0x00000000
+#define PIXELMODE_S_1PPCMAPPED      0x00000008
+#define PIXELMODE_S_2PPC            0x00000010
+#define PIXELMODE_S_4PPC            0x00000018
+#define PIXELMODE_S_8PPC            0x00000020
+#define PIXELMODE_S_223PPC          0x00000028
+#define PIXELMODE_S_DS223PPC        0x00000030
+#define PIXELMODE_S_UNDEF           0x00000038
+
+#define PIXELMODE_M_MASK            0x000003c0
+#define PIXELMODE_M_NOBLINK         0x00000000
+#define PIXELMODE_M_ANDBLINK        0x00000040
+#define PIXELMODE_M_ORBLINK         0x00000080
+#define PIXELMODE_M_XORBLINK        0x000000c0
+#define PIXELMODE_M_BGBLINK         0x00000100
+#define PIXELMODE_M_OFFSINGBLINK    0x00000140
+#define PIXELMODE_M_OFF888BLINK     0x00000180
+#define PIXELMODE_M_DIMBLINK        0x00000300
+#define PIXELMODE_M_BRTBLINK        0x00000340
+#define PIXELMODE_M_DIM888BLINK     0x00000380
+#define PIXELMODE_M_BRT888BLINK     0x000003c0
+
+#define PIXELMODE_C_MASK            0x00003c00
+#define PIXELMODE_C_LUT             0x00000000
+#define PIXELMODE_C_888             0x00001000
+#define PIXELMODE_C_565             0x00001400
+#define PIXELMODE_C_555             0x00001800
+#define PIXELMODE_C_GSLUT           0x00002000
+
+#define PIXELMODE_DSCAN             0x00004000
+#define PIXELMODE_TRBSW             0x00008000
+
+//-----------------------------------------------------------------------------
+//PARLLIFOUT Register Defintions
+//-----------------------------------------------------------------------------
+#define PARLLIFOUT_DAT_MASK         0x0000000f
+#define PARLLIFOUT_DAT_SHIFT        0
+#define PARLLIFOUT_RD               0x00000010
+
+//-----------------------------------------------------------------------------
+//PARLLIFIN Register Defintions
+//-----------------------------------------------------------------------------
+#define PARLLIFIN_DAT_MASK          0x0000000f
+#define PARLLIFIN_DAT_SHIFT         0
+#define PARLLIFIN_CNT_MASK          0x000f0000
+#define PARLLIFIN_CNT_SHIFT         16
+#define PARLLIFIN_ESTRT_MASK        0x00f00000
+#define PARLLIFIN_ESTRT_SHIFT       20
+
+//-----------------------------------------------------------------------------
+// CURSORADRSTART Register Defintions
+//-----------------------------------------------------------------------------
+#define CURSOR_ADR_START_MASK         0xfffffffc
+
+//-----------------------------------------------------------------------------
+// CURSORADRSTART Register Defintions
+//-----------------------------------------------------------------------------
+#define CURSOR_ADR_RESET_MASK         0xfffffffc
+
+//-----------------------------------------------------------------------------
+// CURSORCOLOR1 Register Definitions
+//-----------------------------------------------------------------------------
+#define CURSORCOLOR1_MASK               0x00ffffff
+//-----------------------------------------------------------------------------
+// CURSORCOLOR2 Register Definitions
+//-----------------------------------------------------------------------------
+#define CURSORCOLOR2_MASK               0x00ffffff
+
+//-----------------------------------------------------------------------------
+// CURSORXYLOC Register Definitions
+//-----------------------------------------------------------------------------
+#define CURSORXYLOC_MASK                0x07ff87ff
+#define CURSORXYLOC_XLOC_MASK           0x000007ff
+#define CURSORXYLOC_XLOC_SHIFT          0
+#define CURSORXYLOC_CEN                 0x00008000
+#define CURSORXYLOC_YLOC_MASK           0x07ff0000
+#define CURSORXYLOC_YLOC_SHIFT          16
+
+//-----------------------------------------------------------------------------
+// CURSOR_DSCAN_LH_YLOC Register Definitions
+//-----------------------------------------------------------------------------
+#define CURSOR_DSCAN_LH_YLOC_MASK       0x000087ff
+
+#define CURSOR_DSCAN_LH_YLOC_YLOC_MASK  0x000007ff
+#define CURSOR_DSCAN_LH_YLOC_YLOC_SHIFT 0
+#define CURSOR_DSCAN_LH_YLOC_CLHEN      0x00008000
+
+//-----------------------------------------------------------------------------
+// CURSORSIZE Register Definitions
+//-----------------------------------------------------------------------------
+#define CURSORSIZE_MASK                 0x0000ffff
+
+#define CURSORSIZE_CWID_MASK            0x00000003
+#define CURSORSIZE_CWID_SHIFT           0
+#define CURSORSIZE_CWID_1_WORD          0
+#define CURSORSIZE_CWID_2_WORD          1
+#define CURSORSIZE_CWID_3_WORD          2
+#define CURSORSIZE_CWID_4_WORD          3
+
+#define CURSORSIZE_CLINS_MASK           0x000000fc
+#define CURSORSIZE_CLINS_SHIFT          2
+
+#define CURSORSIZE_CSTEP_MASK           0x00000300
+#define CURSORSIZE_CSTEP_SHIFT          8
+#define CURSORSIZE_CSTEP_1_WORD         0
+#define CURSORSIZE_CSTEP_2_WORD         1
+#define CURSORSIZE_CSTEP_3_WORD         2
+#define CURSORSIZE_CSTEP_4_WORD         3
+
+#define CURSORSIZE_DLNS_MASK            0x0000fc00
+#define CURSORSIZE_DLNS_SHIFT           10
+
+#endif /* _REGS_RASTER_H_ */