
#
# Patch managed by http://www.holgerschurig.de/patcher.html
#

Index: linux-2.6.13/drivers/video/Makefile
===================================================================
--- linux-2.6.13.orig/drivers/video/Makefile	2005-09-14 23:24:09.000000000 +0100
+++ linux-2.6.13/drivers/video/Makefile	2005-09-14 23:29:48.000000000 +0100
@@ -86,6 +86,7 @@
 obj-$(CONFIG_FB_ASILIANT)	  += asiliantfb.o
 obj-$(CONFIG_FB_PXA)		  += pxafb.o
 obj-$(CONFIG_FB_W100)		  += w100fb.o
+obj-$(CONFIG_FB_TC6393)		  += tc6393fb.o
 obj-$(CONFIG_FB_AU1100)		  += au1100fb.o fbgen.o
 obj-$(CONFIG_FB_PMAG_AA)	  += pmag-aa-fb.o
 obj-$(CONFIG_FB_PMAG_BA)	  += pmag-ba-fb.o
Index: linux-2.6.13/drivers/video/Kconfig
===================================================================
--- linux-2.6.13.orig/drivers/video/Kconfig	2005-09-14 23:24:09.000000000 +0100
+++ linux-2.6.13/drivers/video/Kconfig	2005-09-14 23:28:50.000000000 +0100
@@ -1488,6 +1488,23 @@
 
 	  If unsure, say N.
 
+config FB_TC6393
+	tristate "Toshiba TC6393 frame buffer support"
+	depends on FB && TOSHIBA_TC6393
+        select FB_CFB_FILLRECT
+	select FB_CFB_COPYAREA
+	select FB_CFB_IMAGEBLIT
+	select FB_SOFT_CURSOR
+	---help---
+	  Frame buffer driver for the TC6393 as found on the Sharp SL-6000x (tosa) series.
+
+	  This driver is also available as a module ( = code which can be
+	  inserted and removed from the running kernel whenever you want). The
+	  module will be called vfb. If you want to compile it as a module,
+	  say M here and read <file:Documentation/modules.txt>.
+
+	  If unsure, say N.
+
 config FB_PXA_PARAMETERS
 	bool "PXA LCD command line parameters"
 	default n
Index: linux-2.6.13/drivers/video/tc6393fb.c
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ linux-2.6.13/drivers/video/tc6393fb.c	2005-09-14 23:28:50.000000000 +0100
@@ -0,0 +1,675 @@
+/*
+ * linux/drivers/video/tc6393fb.c
+ *
+ * Frame Buffer Device for Toshiba TC6393
+ *
+ * Copyright (c) 2005 Dirk Opfer
+ *
+ *	Based on code written by Sharp/Lineo for 2.4 kernels
+ *
+ *
+ * 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.
+ *
+ * Based on:
+ *  drivers/video/w100fb.c
+ *
+ */
+
+#include <linux/delay.h>
+#include <linux/fb.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/mm.h>
+#include <linux/device.h>
+#include <linux/string.h>
+#include <linux/vmalloc.h>
+
+#include <asm/io.h>
+#include <asm/uaccess.h>
+#include <asm/hardware/tc6393.h>
+#include <video/tc6393fb.h>
+
+#include "tc6393fb.h"
+
+/* Pseudo palette size */
+#define MAX_PALETTES      	16
+#define BITS_PER_PIXEL    	16
+#define LINE_WAIT		20
+#define PLCLN_MASK		0x03FF
+#define REMAPPED_CFG_LEN  	0x100
+#define REMAPPED_MMR_LEN  	0x200 
+#define FB_OFFSET         	0x00100000 
+#define REMAPPED_FB_LEN   	0x100000
+
+#define FIFO_ADDR	(((int)remapped_fbuf)+(1024*1024)-(4*512)) 
+
+static TC6393_REGS kh_cmd[] = 
+{
+	{ KH_BASEADDR_H,	0x0000},         // base address high
+	{ KH_BASEADDR_L,	TC6393_GC_INTERNAL_REG_BASE},  	// base address low
+	{ KH_COMMAND_REG,	0x0002},         // base address enable
+	{ KH_VRAMTC,		0x40a8},         // VRAMRC, VRAMTC
+	{ KH_VRAMAC,		0x0018},         // VRAMSTS, VRAMAC
+	{ KH_VRAMBC,		0x0002},
+};
+
+/* Remapped addresses for base cfg, memmapped regs and the frame buffer itself */
+static void *remapped_lcdbase;
+static void *remapped_inner;
+static void *remapped_fbuf;
+static uint32_t *saved_mem;
+
+/*
+ * Prototypes
+ */
+static void tc6393_acc_init(void);
+static void tc6393_acc_sync(void);
+static void tc6393_soft_reset(struct tc6393fb_par *par);
+static void tc6393fb_save_vidmem(struct tc6393fb_par *par);
+static void tc6393fb_restore_vidmem(struct tc6393fb_par *par);
+
+/* ------------------- chipset specific functions -------------------------- */
+//
+//
+//
+
+static int wait_vsync(struct tc6393fb_par *par)
+{
+  int ct=0;
+  volatile u16 val1,val2;
+
+  u16 line = par->yres;
+  do {
+    val1 = readw(remapped_inner + PLCLN)&PLCLN_MASK;
+    while(val1!=(val2=(readw(remapped_inner + PLCLN)&PLCLN_MASK))) {
+      val1 = val2;
+    }
+    if (val1==line) break;
+    if (++ct>1000*1000/LINE_WAIT) break;
+    udelay(LINE_WAIT);
+  } while(1);
+  if (val1!=line) {
+    printk("unable to wait vsync\n");
+    return 1;
+  }
+  return 0;
+}
+
+static void tc6393_acc_init()
+{
+	tc6393_writew((u16)((FIFO_ADDR>>16)&0x001f), remapped_inner + KH_CMDADR_H);
+	tc6393_writew((u16)(FIFO_ADDR&0x0fff8), remapped_inner + KH_CMDADR_L);
+	tc6393_writew(512-1, remapped_inner + KH_CMDFIF);
+	
+	tc6393_writew(1, remapped_inner + KH_FIFOR);
+	
+	tc6393_writew(0, remapped_inner + KH_BINTMSK);
+	tc6393_writew(0, remapped_inner + KH_CMDFINT);
+}
+
+static void tc6393_acc_write( u32* cmd, int cmdnum )
+{
+	volatile int i;
+	int ct=0;
+	
+	if (readw(remapped_inner + KH_FIPT)>400) {
+	  while(readw(remapped_inner + KH_FIPT)>200) {
+	    mdelay(1);
+	    if (++ct>1000) {
+		printk(": timeout\n");
+		return; // timeout
+	    }
+	  }
+	}
+	
+	for ( i = 0; i < cmdnum; i ++ ) {
+	  tc6393_writew((u16)((cmd[i]>>16) & 0x0ffff), remapped_inner + KH_COMD_H);
+	  tc6393_writew((u16)(cmd[i] & 0x0ffff), remapped_inner + KH_COMD_L);
+	}
+}
+
+static void tc6393_acc_sync()
+{
+	int ct=0;
+	while(readw(remapped_inner + KH_FIPT)>0) {
+	  mdelay(1);
+	  if (++ct>1000) {
+	printk(": timeout\n");
+	    return; // timeout
+	  }
+	}
+	ct=0;
+	while(readw(remapped_inner + KH_DMAST)&PXAIO_DMAST_BLT) {
+	  mdelay(1);
+	  if (++ct>1000) {
+	    printk(": timeout\n");
+	    return; // timeout
+	  }
+	}
+}
+
+
+static void tc6393_clear_screen(struct tc6393fb_par *par)
+{
+
+	static u32 cmd[6];
+	u16 xres = par->xres;
+	u16 yres = par->yres;
+	
+	cmd[0] = PXAIO_COMDI_DSADR|PXAIO_COMDD_DSADR(((int)remapped_fbuf));
+	cmd[1] = PXAIO_COMDI_DHPIX|PXAIO_COMDD_DHPIX((xres - 1));
+	cmd[2] = PXAIO_COMDI_DVPIX|(PXAIO_COMDD_DVPIX((yres - 1)));
+	cmd[3] = PXAIO_COMDI_FILL|PXAIO_COMDD_FILL(0xffff);
+	cmd[4] = PXAIO_COMDI_FLGO;
+	
+	tc6393_acc_write(cmd,5);
+	tc6393_acc_sync();
+
+}
+
+static void tc6393_hw_init(struct tc6393fb_par *par)
+{
+
+	tc6393_soft_reset(par);
+	tc6393_acc_init();
+
+}
+
+static void tc6393fb_lcdhwsetup(struct tc6393fb_par *par)
+{
+	struct tc6393fb_mode *mode = par->mode;
+	struct tc6393fb_tg_info *tg = par->mach->tg;
+
+	tc6393_writew(0x0000, remapped_inner + PLGMD);
+	reset_tc6393_bit(par->parent_dev, TC6393_SYS_FER, FUNC_SLCDEN);
+	tc6393_writew(PLCNT_DEFAULT, remapped_inner + PLCNT);
+
+	write_tc6393_reg(par->parent_dev, TC6393_SYS_PLL1CR1, mode->reg_pll10);
+	write_tc6393_reg(par->parent_dev, TC6393_SYS_PLL1CR2, mode->reg_pll11);
+
+	set_tc6393_bit(par->parent_dev, TC6393_SYS_FER, FUNC_SLCDEN);
+
+	tc6393_writew(mode->reg_vhlin	, remapped_inner + VHLIN   );
+	tc6393_writew(mode->reg_pldsa_h	, remapped_inner + PLDSA_H );
+	tc6393_writew(mode->reg_pldsa_l	, remapped_inner + PLDSA_L );
+	tc6393_writew(mode->reg_plpit_h	, remapped_inner + PLPIT_H );
+	tc6393_writew(mode->reg_plpit_l	, remapped_inner + PLPIT_L );
+	tc6393_writew(mode->reg_plht	, remapped_inner + PLHT    );
+	tc6393_writew(mode->reg_plhds	, remapped_inner + PLHDS   );
+	tc6393_writew(mode->reg_plhss	, remapped_inner + PLHSS   );
+	tc6393_writew(mode->reg_plhse	, remapped_inner + PLHSE   );
+	tc6393_writew(mode->reg_plhpx	, remapped_inner + PLHPX   );
+	tc6393_writew(mode->reg_plvt	, remapped_inner + PLVT    );
+	tc6393_writew(mode->reg_plvds	, remapped_inner + PLVDS   );
+	tc6393_writew(mode->reg_plvss	, remapped_inner + PLVSS   );
+	tc6393_writew(mode->reg_plvse	, remapped_inner + PLVSE   );
+	tc6393_writew(mode->reg_misc	, remapped_inner + MISC    );
+	tc6393_writew(mode->reg_plgmd	, remapped_inner + PLGMD   );
+	tc6393_writew(mode->reg_plcst	, remapped_inner + PLCST   );
+	tc6393_writew(mode->reg_plmod	, remapped_inner + PLMOD   );
+
+	tc6393_writew(PLCNT_DEFAULT, remapped_inner + PLCNT);
+	mdelay(5);
+	tc6393_writew(PLCNT_DEFAULT | PLCNT_STOP_CKP, remapped_inner+PLCNT);
+	mdelay(5);
+
+	tc6393_writew(PLCNT_DEFAULT | PLCNT_STOP_CKP | PLCNT_SOFT_RESET, remapped_inner + PLCNT);
+
+	tc6393_writew(0xfffa, remapped_inner + PIFEN);
+
+	if (tg && tg->tg_on)
+		tg->tg_on(par);
+}
+
+static void tc6393_soft_reset(struct tc6393fb_par *par)
+{
+	int i;
+	struct tc6393fb_mode *mode = par->mode;
+	struct tc6393fb_tg_info *tg = par->mach->tg;
+
+	if (tg && tg->init)
+		tg->init(par);
+
+	// Clock Control Register
+	set_tc6393_bit(par->parent_dev, TC6393_SYS_CCR, CLKCTL_CONFIG_DTA);
+
+	write_tc6393_reg(par->parent_dev, TC6393_SYS_PLL1CR1, mode->reg_pll10);
+	write_tc6393_reg(par->parent_dev, TC6393_SYS_PLL1CR2, mode->reg_pll11);
+
+	tc6393_writew(0x003a, remapped_lcdbase + KH_CLKEN);
+	tc6393_writew(0x003a, remapped_lcdbase + KH_GCLKEN);
+	tc6393_writew(0x3f00, remapped_lcdbase + KH_PSWCLR);
+
+	set_tc6393_bit(par->parent_dev, TC6393_SYS_FER, FUNC_SLCDEN);
+	mdelay(2);
+
+	tc6393_writew(0x0000, remapped_lcdbase + KH_PSWCLR);
+
+	// initialize kurohyo configuration register
+	for( i=0; i <= ARRAY_SIZE(kh_cmd); i++){
+		tc6393_writew((u16)(kh_cmd[i].Value), remapped_lcdbase + kh_cmd[i].Index);
+	}
+	mdelay(2);
+	tc6393_writew(0x000b, remapped_lcdbase + KH_VRAMBC);
+
+}
+
+
+static void tc6393_suspend(struct tc6393fb_par *par)
+{
+
+	struct tc6393fb_tg_info *tg = par->mach->tg;
+
+	tc6393_acc_sync();
+
+	wait_vsync(par);
+	tc6393_clear_screen(par);
+	wait_vsync(par);
+	wait_vsync(par);
+
+	// TG OFF
+	if (tg && tg->tg_off)
+		tg->tg_off(par);
+}
+
+static void tc6393_resume(struct tc6393fb_par *par)
+{
+
+	tc6393_soft_reset(par);
+	tc6393_acc_init();
+
+	// erase whole VRAM
+//	if (tc6393fb_lcdMode == LCD_MODE_QVGA) {
+//		memset(remapped_fbuf,0xff,MAX_XRES_VGA*MAX_YRES_VGA*2);
+//	}
+
+	tc6393fb_lcdhwsetup(par);
+
+}
+
+
+
+/*
+ * Set a palette value from rgb components
+ */
+static int tc6393fb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
+			     u_int trans, struct fb_info *info)
+{
+	unsigned int val;
+	int ret = 1;
+
+	/*
+	 * If greyscale is true, then we convert the RGB value
+	 * to greyscale no matter what visual we are using.
+	 */
+	if (info->var.grayscale)
+		red = green = blue = (19595 * red + 38470 * green + 7471 * blue) >> 16;
+
+	/*
+	 * 16-bit True Colour.  We encode the RGB value
+	 * according to the RGB bitfield information.
+	 */
+	if (regno < MAX_PALETTES) {
+
+		uint32_t *pal = info->pseudo_palette;
+
+		val = (red & 0xf800) | ((green & 0xfc00) >> 5) | ((blue & 0xf800) >> 11);
+		pal[regno] = val;
+		ret = 0;
+	}
+	return ret;
+}
+
+
+/*
+ * Blank the display based on value in blank_mode
+ */
+static int tc6393fb_blank(int blank_mode, struct fb_info *info)
+{
+	struct tc6393fb_par *par = info->par;
+
+	switch(blank_mode) {
+
+ 	case FB_BLANK_NORMAL:         /* Normal blanking */
+	case FB_BLANK_VSYNC_SUSPEND:  /* VESA blank (vsync off) */
+	case FB_BLANK_HSYNC_SUSPEND:  /* VESA blank (hsync off) */
+ 	case FB_BLANK_POWERDOWN:      /* Poweroff */
+  		if (par->blanked == 0) {
+    			tc6393fb_save_vidmem(par);
+			par->blanked = 1;
+  		}
+  		break;
+
+ 	case FB_BLANK_UNBLANK: /* Unblanking */
+  		if (par->blanked != 0) {
+    			tc6393fb_restore_vidmem(par);
+			par->blanked = 0;
+  		}
+  		break;
+ 	}
+	return 0;
+}
+
+
+/*
+ *  Change the resolution by calling the appropriate hardware functions
+ */
+static void tc6393fb_activate_var(struct tc6393fb_par *par)
+{
+	struct tc6393fb_tg_info *tg = par->mach->tg;
+
+	if (tg && tg->init)
+		tg->init(par);
+	
+	tc6393fb_lcdhwsetup(par);
+	tc6393_clear_screen(par);
+
+//	if (!par->blanked && par->mach->tg) par->mach->tg->change(par);
+}
+
+
+/* Select the smallest mode that allows the desired resolution to be
+ * displayed. If desired, the x and y parameters can be rounded up to
+ * match the selected mode.
+ */
+static struct tc6393fb_mode *tc6393fb_get_mode(struct tc6393fb_par *par, unsigned int *x, unsigned int *y, int saveval)
+{
+	struct tc6393fb_mode *mode = NULL;
+	struct tc6393fb_mode *modelist = par->mach->modelist;
+	unsigned int best_x = 0xffffffff, best_y = 0xffffffff;
+	unsigned int i;
+
+	for (i = 0 ; i < par->mach->num_modes ; i++) {
+		if (modelist[i].xres >= *x && modelist[i].yres >= *y &&
+				modelist[i].xres < best_x && modelist[i].yres < best_y) {
+			best_x = modelist[i].xres;
+			best_y = modelist[i].yres;
+			mode = &modelist[i];
+		} else if(modelist[i].xres >= *y && modelist[i].yres >= *x &&
+		        modelist[i].xres < best_y && modelist[i].yres < best_x) {
+			best_x = modelist[i].yres;
+			best_y = modelist[i].xres;
+			mode = &modelist[i];
+		}
+	}
+
+	if (mode && saveval) {
+		*x = best_x;
+		*y = best_y;
+	}
+	
+	return mode;
+}
+
+
+/*
+ *  tc6393fb_check_var():
+ *  Get the video params out of 'var'. If a value doesn't fit, round it up,
+ *  if it's too big, return -EINVAL.
+ */
+static int tc6393fb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
+{
+	struct tc6393fb_par *par=info->par;
+
+	if(!tc6393fb_get_mode(par, &var->xres, &var->yres, 1))
+		return -EINVAL;
+
+	var->xres_virtual = max(var->xres_virtual, var->xres);
+	var->yres_virtual = max(var->yres_virtual, var->yres);
+
+	if (var->bits_per_pixel > BITS_PER_PIXEL)
+		return -EINVAL;
+	else
+		var->bits_per_pixel = BITS_PER_PIXEL;
+
+	var->red.offset = 11;
+	var->red.length = 5;
+	var->green.offset = 5;
+	var->green.length = 6;
+	var->blue.offset = 0;
+	var->blue.length = 5;
+	var->transp.offset = var->transp.length = 0;
+
+	var->nonstd = 0;
+	var->height = -1;
+	var->width = -1;
+	var->vmode = FB_VMODE_NONINTERLACED;
+	var->sync = 0;
+	var->pixclock = 0x04;  /* 171521; */
+
+	return 0;
+}
+
+
+/*
+ * tc6393fb_set_par():
+ * Set the user defined part of the display for the specified console
+ *  by looking at the values in info.var
+ */
+static int tc6393fb_set_par(struct fb_info *info)
+{
+	struct tc6393fb_par *par=info->par;
+
+	if (par->xres != info->var.xres || par->yres != info->var.yres)
+	{
+		par->xres = info->var.xres;
+		par->yres = info->var.yres;
+		par->mode = tc6393fb_get_mode(par, &par->xres, &par->yres, 0);
+
+		info->fix.visual = FB_VISUAL_TRUECOLOR;
+		info->fix.ypanstep = 0;
+		info->fix.ywrapstep = 0;
+		info->fix.line_length = par->xres * BITS_PER_PIXEL / 8;
+		info->fix.smem_len = (par->yres * par->xres * BITS_PER_PIXEL) / 8;;
+
+		tc6393fb_activate_var(par);
+	}
+	return 0;
+}
+
+
+/*
+ *  Frame buffer operations
+ */
+static struct fb_ops tc6393fb_ops = {
+	.owner        = THIS_MODULE,
+	.fb_check_var = tc6393fb_check_var,
+	.fb_set_par   = tc6393fb_set_par,
+	.fb_setcolreg = tc6393fb_setcolreg,
+	.fb_blank     = tc6393fb_blank,
+	.fb_fillrect  = cfb_fillrect,
+	.fb_copyarea  = cfb_copyarea,
+	.fb_imageblit = cfb_imageblit,
+	.fb_cursor    = soft_cursor,
+};
+
+
+static void tc6393fb_save_vidmem(struct tc6393fb_par *par)
+{
+	int memsize = REMAPPED_FB_LEN;
+	
+	saved_mem = vmalloc(memsize);
+	if (saved_mem) 
+		memcpy(saved_mem, remapped_fbuf, memsize);
+}
+		
+static void tc6393fb_restore_vidmem(struct tc6393fb_par *par)
+{
+	int memsize = REMAPPED_FB_LEN;
+		
+	if (saved_mem) {
+		memcpy(remapped_fbuf, saved_mem, memsize);
+		vfree(saved_mem);
+	}
+}
+
+
+#ifdef CONFIG_PM
+static int tc6393fb_suspend(struct tc6393_dev * dev, u32 state, u32 level)
+{
+	if (level == SUSPEND_POWER_DOWN) {
+		struct fb_info *info = tc6393_get_drvdata(dev);
+		struct tc6393fb_par *par=info->par;
+
+		tc6393fb_save_vidmem(par);
+		tc6393_suspend(par);
+		par->blanked = 1;
+	}
+	return 0;
+}
+
+static int tc6393fb_resume(struct tc6393_dev * dev, u32 level)
+{
+	if (level == RESUME_POWER_ON) {
+		struct fb_info *info = tc6393_get_drvdata(dev);
+		struct tc6393fb_par *par=info->par;
+
+		tc6393_resume(par);
+		tc6393fb_restore_vidmem(par);
+		par->blanked = 0;;
+	}
+	return 0;
+}
+#else
+#define tc6393fb_suspend  NULL
+#define tc6393fb_resume   NULL
+#endif
+
+
+int __init tc6393fb_probe(struct tc6393_dev *dev)
+{
+	int err = -EIO;
+	struct tc6393fb_mach_info *inf;
+	struct fb_info *info = NULL;
+	struct tc6393fb_par *par;
+
+	remapped_lcdbase = (void *) (TC6393_GC_BASE + dev->mapbase);
+	remapped_inner = (void *) (TC6393_GC_INTERNAL_REG_BASE + dev->mapbase);
+	remapped_fbuf = (void *) (TC6393_RAM1_BASE + dev->mapbase);
+
+	info=framebuffer_alloc(sizeof(struct tc6393fb_par), &dev->dev);
+
+	if (!info) {
+		err = -ENOMEM;
+		goto out;
+	}
+
+	par = info->par;
+	tc6393_set_drvdata(dev, info);
+
+	inf = dev->dev.platform_data;
+	
+	par->parent_dev = dev->dev.parent;
+	par->mach = inf;
+	par->blanked = 0;
+
+	info->pseudo_palette = kmalloc(sizeof (uint32_t) * MAX_PALETTES, GFP_KERNEL);
+	if (!info->pseudo_palette) {
+		err = -ENOMEM;
+		goto out;
+	}
+
+	info->fbops = &tc6393fb_ops;
+	info->flags = FBINFO_DEFAULT;
+	info->node = -1;
+	info->screen_base = remapped_fbuf;
+	info->screen_size = REMAPPED_FB_LEN;
+
+
+	strcpy(info->fix.id, "TC6393FB");
+	info->fix.type = FB_TYPE_PACKED_PIXELS;
+	info->fix.type_aux = 0;
+	info->fix.accel = FB_ACCEL_NONE;
+
+	info->fix.smem_start = (int) inf->fb_base + FB_OFFSET;
+	info->fix.mmio_start = (int) inf->fb_base + 0x500;
+
+	info->fix.mmio_len = REMAPPED_CFG_LEN + REMAPPED_MMR_LEN; // LCD-COMMON+LCD-MMR
+
+	par->mode = &inf->modelist[0];
+	info->var.xres = par->mode->xres;
+	info->var.yres = par->mode->yres;
+
+	info->var.xres_virtual = info->var.xres;
+	info->var.yres_virtual = info->var.yres;
+	info->var.pixclock = 0x04;  /* 171521; */
+	info->var.sync = 0;
+	info->var.grayscale = 0;
+	info->var.xoffset = info->var.yoffset = 0;
+	info->var.accel_flags = 0;
+	info->var.activate = FB_ACTIVATE_NOW;
+
+	tc6393_hw_init(par);
+	
+	if ( tc6393fb_check_var(&info->var, info) < 0) {
+		err = -EINVAL;
+		goto out;
+	}
+
+	tc6393fb_set_par(info);
+
+	if (register_framebuffer(info) < 0) {
+		err = -EINVAL;
+		goto out;
+	}
+
+
+	printk(KERN_INFO "fb%d: %s frame buffer device\n", info->node, info->fix.id);
+	return 0;
+	
+out:
+	kfree(info->pseudo_palette);
+
+	if (info)
+		framebuffer_release(info);			
+	return err;
+}
+
+static int tc6393fb_remove(struct tc6393_dev *dev)
+{
+	struct fb_info *info = tc6393_get_drvdata(dev);
+
+	unregister_framebuffer(info);
+
+	kfree(info->pseudo_palette);
+
+	framebuffer_release(info);
+
+	return 0;
+}
+
+static struct tc6393_driver tc6393fb_driver = {
+	.drv = {
+		.name = "tc6393-fb"
+	},
+	.devid	= TC6393_DEVID_FB,
+	.probe	= tc6393fb_probe,
+	.remove	= tc6393fb_remove,
+	.suspend= tc6393fb_suspend,
+	.resume	= tc6393fb_resume,
+	
+};
+
+int __init tc6393fb_init(void)
+{
+	return tc6393_driver_register(&tc6393fb_driver);
+}
+
+void __exit tc6393fb_cleanup(void)
+{
+ 	tc6393_driver_unregister(&tc6393fb_driver);
+}
+
+module_init(tc6393fb_init);
+module_exit(tc6393fb_cleanup);
+
+MODULE_DESCRIPTION("TC6393 framebuffer driver");
+MODULE_LICENSE("GPLv2");
Index: linux-2.6.13/drivers/video/tc6393fb.h
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ linux-2.6.13/drivers/video/tc6393fb.h	2005-09-14 23:28:50.000000000 +0100
@@ -0,0 +1,185 @@
+/*
+ * linux/drivers/video/tc6393fb.h
+ *
+ * Frame Buffer Device for TOSHIBA tc6393
+ *
+ * (C) Copyright 2004 Lineo Solutions, Inc.
+ *
+ * May be copied or modified under the terms of the GNU General Public
+ * License.  See linux/COPYING for more information.
+ *
+ */
+
+#if !defined (_TC6393FB)
+#define _TC6393FB
+
+#define KH_COMMAND_REG		0x004
+#define KH_BASEADDR_H		0x012
+#define KH_BASEADDR_L		0x010
+#define KH_CLKEN		0x040
+#define KH_GCLKEN		0x042
+#define KH_PSWCLR		0x050
+#define KH_VRAMTC		0x060
+#define KH_VRAMRC		0x061
+#define KH_VRAMAC		0x062
+#define KH_VRAMBC		0x064
+#define KH_VMREQMD		0x06F
+
+#define KH_CMDADR_L		0x00A
+#define KH_CMDADR_H		0x00C
+#define KH_CMDFIF		0x00E
+#define KH_CMDFINT		0x010
+#define KH_BINTMSK		0x012
+#define KH_BINTST		0x014
+#define KH_FIPT			0x016
+#define KH_DMAST		0x018
+#define KH_COMD_L		0x01C
+#define KH_COMD_H		0x01E
+#define KH_FIFOR		0x022
+
+#define	PXAIO_DMAST_DMA		0x0001
+#define	PXAIO_DMAST_BLT		0x0002
+
+
+#define PLMOD          		0x164
+#define PLCST              	0x102
+#define VHLIN              	0x008
+#define PLDSA_H            	0x124
+#define PLDSA_L            	0x122
+#define PLPIT_H            	0x12c
+#define PLPIT_L            	0x12a
+#define PLHT               	0x140
+#define PLHDS              	0x142
+#define PLHSS              	0x144
+#define PLHSE              	0x146
+#define PLHBS              	0x148
+#define PLHBE              	0x14a
+#define PLHPX              	0x14c
+#define PLVT               	0x150
+#define PLVDS              	0x152
+#define PLVSS              	0x154
+#define PLVSE              	0x156
+#define PLVBS              	0x158
+#define PLVBE              	0x15a
+#define PLGMD              	0x12e
+#define PLCST              	0x102
+#define PLMOD              	0x164
+#define MISC               	0x166
+#define PLCNT              	0x100
+#define PIFEN              	0x18e
+#define PLCLN		   	0x160
+
+
+#define CLKCTL_USB_MASK    	0x0002
+#define CLKCTL_CONFIG_DTA  	0x1310
+
+#define PLCNT_SOFT_RESET	0x0001
+#define PLCNT_STOP_CKP		0x0004
+#define PLCNT_DEFAULT		0x0010
+
+
+
+#define FUNC_SLCDEN 		0x0004
+
+typedef struct
+{
+    unsigned short Index;
+    unsigned short Value;
+} TC6393_REGS;
+
+
+/*
+ * Accelerator COMMAND
+ */
+
+// Set Command
+#define	PXAIO_COMDI_CSADR	0x00000000
+#define	PXAIO_COMDD_CSADR(x)	(x&0x001ffffe)
+#define	PXAIO_COMDI_CHPIX	0x01000000
+#define	PXAIO_COMDD_CHPIX(x)	(x&0x000003ff)
+#define	PXAIO_COMDI_CVPIX	0x02000000
+#define	PXAIO_COMDD_CVPIX(x)	(x&0x000003ff)
+#define	PXAIO_COMDI_PSADR	0x03000000
+#define	PXAIO_COMDD_PSADR(x)	(x&0x00fffffe)
+#define	PXAIO_COMDI_PHPIX	0x04000000
+#define	PXAIO_COMDD_PHPIX(x)	(x&0x000003ff)
+#define	PXAIO_COMDI_PVPIX	0x05000000
+#define	PXAIO_COMDD_PVPIX(x)	(x&0x000003ff)
+#define	PXAIO_COMDI_PHOFS	0x06000000
+#define	PXAIO_COMDD_PHOFS(x)	(x&0x000003ff)
+#define	PXAIO_COMDI_PVOFS	0x07000000
+#define	PXAIO_COMDD_PVOFS(x)	(x&0x000003ff)
+#define	PXAIO_COMDI_POADR	0x08000000
+#define	PXAIO_COMDD_POADR(x)	(x&0x00fffffe)
+#define	PXAIO_COMDI_RSTR	0x09000000
+#define	PXAIO_COMDD_RSTR(x)	(x&0x000000ff)
+#define	PXAIO_COMDI_TCLOR	0x0A000000
+#define	PXAIO_COMDD_TCLOR(x)	(x&0x0000ffff)
+#define	PXAIO_COMDI_FILL	0x0B000000
+#define	PXAIO_COMDD_FILL(x)	(x&0x0000ffff)
+#define	PXAIO_COMDI_DSADR	0x0C000000
+#define	PXAIO_COMDD_DSADR(x)	(x&0x00fffffe)
+#define	PXAIO_COMDI_SSADR	0x0D000000
+#define	PXAIO_COMDD_SSADR(x)	(x&0x00fffffe)
+#define	PXAIO_COMDI_DHPIX	0x0E000000
+#define	PXAIO_COMDD_DHPIX(x)	(x&0x000003ff)
+#define	PXAIO_COMDI_DVPIX	0x0F000000
+#define	PXAIO_COMDD_DVPIX(x)	(x&0x000003ff)
+#define	PXAIO_COMDI_SHPIX	0x10000000
+#define	PXAIO_COMDD_SHPIX(x)	(x&0x000003ff)
+#define	PXAIO_COMDI_SVPIX	0x11000000
+#define	PXAIO_COMDD_SVPIX(x)	(x&0x000003ff)
+#define	PXAIO_COMDI_LBINI	0x12000000
+#define	PXAIO_COMDD_LBINI(x)	(x&0x0000ffff)
+#define	PXAIO_COMDI_LBK2	0x13000000
+#define	PXAIO_COMDD_LBK2(x)	(x&0x0000ffff)
+#define	PXAIO_COMDI_SHBINI	0x14000000
+#define	PXAIO_COMDD_SHBINI(x)	(x&0x0000ffff)
+#define	PXAIO_COMDI_SHBK2	0x15000000
+#define	PXAIO_COMDD_SHBK2(x)	(x&0x0000ffff)
+#define	PXAIO_COMDI_SVBINI	0x16000000
+#define	PXAIO_COMDD_SVBINI(x)	(x&0x0000ffff)
+#define	PXAIO_COMDI_SVBK2	0x17000000
+#define	PXAIO_COMDD_SVBK2(x)	(x&0x0000ffff)
+
+// Action Command
+#define	PXAIO_COMDI_CMGO	0x20000000
+#define	PXAIO_COMDD_CMGO_CEND	0x00000001
+#define	PXAIO_COMDD_CMGO_INT	0x00000002
+#define	PXAIO_COMDD_CMGO_CMOD	0x00000010
+#define	PXAIO_COMDD_CMGO_CDVRV	0x00000020
+#define	PXAIO_COMDD_CMGO_CDHRV	0x00000040
+#define	PXAIO_COMDD_CMGO_RUND	0x00008000
+#define	PXAIO_COMDI_SCGO	0x21000000
+#define	PXAIO_COMDD_SCGO_CEND	0x00000001
+#define	PXAIO_COMDD_SCGO_INT	0x00000002
+#define	PXAIO_COMDD_SCGO_ROP3	0x00000004
+#define	PXAIO_COMDD_SCGO_TRNS	0x00000008
+#define	PXAIO_COMDD_SCGO_DVRV	0x00000010
+#define	PXAIO_COMDD_SCGO_DHRV	0x00000020
+#define	PXAIO_COMDD_SCGO_SVRV	0x00000040
+#define	PXAIO_COMDD_SCGO_SHRV	0x00000080
+// Specifications Document Rev.18 Add
+#define	PXAIO_COMDD_SCGO_DSTXY	0x00008000
+#define	PXAIO_COMDI_SBGO	0x22000000
+#define	PXAIO_COMDD_SBGO_CEND	0x00000001
+#define	PXAIO_COMDD_SBGO_INT	0x00000002
+#define	PXAIO_COMDD_SBGO_DVRV	0x00000010
+#define	PXAIO_COMDD_SBGO_DHRV	0x00000020
+#define	PXAIO_COMDD_SBGO_SVRV	0x00000040
+#define	PXAIO_COMDD_SBGO_SHRV	0x00000080
+#define	PXAIO_COMDD_SBGO_SBMD	0x00000100
+#define	PXAIO_COMDI_FLGO	0x23000000
+#define	PXAIO_COMDD_FLGO_CEND	0x00000001
+#define	PXAIO_COMDD_FLGO_INT	0x00000002
+#define	PXAIO_COMDD_FLGO_ROP3	0x00000004
+#define	PXAIO_COMDI_LDGO	0x24000000
+#define	PXAIO_COMDD_LDGO_CEND	0x00000001
+#define	PXAIO_COMDD_LDGO_INT	0x00000002
+#define	PXAIO_COMDD_LDGO_ROP3	0x00000004
+#define	PXAIO_COMDD_LDGO_ENDPX	0x00000008
+#define	PXAIO_COMDD_LDGO_LVRV	0x00000010
+#define	PXAIO_COMDD_LDGO_LHRV	0x00000020
+#define	PXAIO_COMDD_LDGO_LDMOD	0x00000040
+
+#endif
Index: linux-2.6.13/include/video/tc6393fb.h
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ linux-2.6.13/include/video/tc6393fb.h	2005-09-14 23:28:50.000000000 +0100
@@ -0,0 +1,71 @@
+/*
+ *  Support for the TC6393 frame buffer.
+ *
+ *  Copyright (c) 2005 Dirk Opfer
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 as
+ *  published by the Free Software Foundation.
+ */
+
+struct tc6393fb_par;
+
+/* LCD Specific Routines and Config */
+struct tc6393fb_tg_info {
+	void (*init)(struct tc6393fb_par*);
+	void (*change)(struct tc6393fb_par*);
+	void (*tg_on)(struct tc6393fb_par*);
+	void (*tg_off)(struct tc6393fb_par*);
+};
+
+
+/* LCD Mode definition */
+struct tc6393fb_mode {
+	unsigned int xres;
+	unsigned int yres;
+	unsigned short reg_vhlin;       // VHLIN
+        unsigned short reg_pldsa_h;     // PLDSA display start address high
+        unsigned short reg_pldsa_l;     // PLDSA display start address low
+        unsigned short reg_plpit_h;     // PLPIT horizontal pixel high
+        unsigned short reg_plpit_l;     // PLPIT horizontal pixel low
+        unsigned short reg_plht;        // PLHT  horizontal total
+        unsigned short reg_plhds;       // PLHDS horizontal display start
+        unsigned short reg_plhss;       // PLHSS H-sync start
+        unsigned short reg_plhse;       // PLHPX Horizontal number of pixel
+        unsigned short reg_plhpx;       // PLVT  Vertical total
+        unsigned short reg_plvt;        // PLVT  Vertical total
+        unsigned short reg_plvds;       // PLVDS Vertical display start
+        unsigned short reg_plvss;       // PLVSS V-sync start
+        unsigned short reg_plvse;       // PLVSE V-sync end
+        unsigned short reg_misc;;       // MISC  RGB565 mode
+        unsigned short reg_plgmd;       // PLGMD vram access enable
+        unsigned short reg_plcst;       // PLCST
+        unsigned short reg_plmod;	// PLMOD Sync polarity
+        unsigned short reg_pll10;
+        unsigned short reg_pll11;
+};
+
+
+/*
+ * This structure describes the machine which we are running on.
+ * It is set by machine specific code and used in the probe routine
+ * of drivers/video/tc6393fb.c
+ */
+struct tc6393fb_mach_info {
+	/* Table of modes the LCD is capable of */
+	struct tc6393fb_mode *modelist;
+	unsigned int num_modes;
+	void * fb_base;
+	/* Hooks for any platform specific tg/lcd code (optional) */
+	struct tc6393fb_tg_info *tg;
+};
+
+/* General frame buffer data structure */
+struct tc6393fb_par {
+	unsigned int xres;
+	unsigned int yres;
+	unsigned int blanked;
+	struct tc6393fb_mode *mode;
+	struct device *parent_dev;
+	struct tc6393fb_mach_info *mach;
+};

