--- linux-2.6.17-vanilla/drivers/video/epson1356fb.c	1970-01-01 00:00:00.000000000 +0000
+++ linux-2.6.17/drivers/video/epson1356fb.c	2006-07-10 17:06:11.000000000 +0000
@@ -0,0 +1,345 @@
+/*
+ * linux/drivers/video/epson1356fb.c -- Epson 1356 LCD Controller Frame Buffer Device
+ *
+ *  Copyright (C) 2001 MIT
+ *
+ * Edited from sa1100fb.c
+ *  Copyright (C) 1999 Eric A. Thomas
+ *   Based on acornfb.c Copyright (C) Russell King.
+ *
+ * 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.
+ * 
+ * 20050203: Ported to kernel 2.6. Very basic interface for the Jornada 720 (C) Alex Lange (chicken@handhelds.org)
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/interrupt.h>
+#include <linux/slab.h>
+#include <linux/fb.h>
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/ioport.h>
+#include <linux/device.h>
+#include <linux/dma-mapping.h>
+
+#include <asm/uaccess.h>
+#include <asm/hardware.h>
+
+#include <asm/arch/jornada720.h>
+
+#include "console/fbcon.h"
+
+u32 pseudo_pal[16];
+
+struct fb_info fb_info;
+
+static int e1356fb_setcolreg(unsigned regno, unsigned red, unsigned green,
+			      unsigned blue, unsigned transp,
+			      struct fb_info *fb_info)
+{
+	int bpp, m = 0;
+
+	bpp = fb_info->var.bits_per_pixel;
+	m = (bpp <= 8) ? (1 << bpp) : 256;
+	if (regno >= m) {
+		printk("regno %d out of range (max %d)\n", regno, m);
+		return -EINVAL;
+	}
+	switch (bpp) {
+	case 8:
+		break;
+	case 16:
+		/* RGB 565 */
+		pseudo_pal[regno] = ((red & 0xF800) |
+					   ((green & 0xFC00) >> 5) |
+					   ((blue & 0xF800) >> 11));
+		break;
+	}
+
+	return 0;
+}
+
+static int e1356fb_blank(int blank, struct fb_info *info)
+{
+	switch (blank) {
+		case FB_BLANK_POWERDOWN:
+		case FB_BLANK_VSYNC_SUSPEND:
+		case FB_BLANK_HSYNC_SUSPEND:
+		case FB_BLANK_NORMAL:
+			PPSR &= ~PPC_LDD1;
+			PPDR |= PPC_LDD1;
+			break;
+
+		case FB_BLANK_UNBLANK:
+			PPSR |= PPC_LDD1;
+			mdelay(100);
+		}
+	return 0;
+}
+
+static struct fb_var_screeninfo e1356fb_screeninfo = {
+	.xres 		= 640,
+	.yres 		= 240,
+	.xres_virtual 	= 640,
+	.yres_virtual 	= 240,
+	.bits_per_pixel = 16,
+	.red.length	= 5,
+	.green.length	= 6,
+	.blue.length	= 5,
+	.transp.length	= 0,
+	.red.offset	= 11,
+	.green.offset	= 5,
+	.blue.offset	= 0,
+	.transp.offset	= 0,
+	.activate 	= FB_ACTIVATE_NOW,
+	.height 	= -1,
+	.width 		= -1,
+	.vmode 		= FB_VMODE_NONINTERLACED,
+	.accel_flags	= 0,
+	.nonstd		= 0,
+};
+
+static struct fb_ops e1356fb_ops = {
+	.owner		= THIS_MODULE,
+	.fb_setcolreg	= e1356fb_setcolreg,
+	.fb_fillrect	= cfb_fillrect,
+	.fb_copyarea	= cfb_copyarea,
+	.fb_imageblit	= cfb_imageblit,		
+	.fb_cursor	= soft_cursor,
+	.fb_blank	= e1356fb_blank,
+};
+
+static struct fb_fix_screeninfo e1356fb_fix = {
+	.id 		= "e1356fb",
+	.smem_len 	= (MAX_XRES * MAX_YRES * MAX_BPP)/8,
+	.smem_start	= (unsigned long)DISP_MEM_OFFSET_PHYS,
+	.type 		= FB_TYPE_PACKED_PIXELS,
+	.visual 	= FB_VISUAL_TRUECOLOR,
+	.line_length 	= (640 * 16) / 8,
+	.accel		= FB_ACCEL_NONE,
+	.type_aux	= 0,
+	.ypanstep	= 0,
+	.ywrapstep	= 0,
+};
+
+unsigned char LUT8[256*3] = {
+	/* Primary and secondary colors */
+	0x00, 0x00, 0x00,  0x00, 0x00, 0xA0,  0x00, 0xA0, 0x00,  0x00, 0xA0, 0xA0,
+	0xA0, 0x00, 0x00,  0xA0, 0x00, 0xA0,  0xA0, 0xA0, 0x00,  0xA0, 0xA0, 0xA0,
+	0x50, 0x50, 0x50,  0x00, 0x00, 0xF0,  0x00, 0xF0, 0x00,  0x00, 0xF0, 0xF0,
+	0xF0, 0x00, 0x00,  0xF0, 0x00, 0xF0,  0xF0, 0xF0, 0x00,  0xF0, 0xF0, 0xF0
+};
+
+static char lut_base[] = {
+	/*red    green  blue   rinc   ginc   binc  */
+	  0x00,  0x00,  0x00,  0x10,  0x10,  0x10, /* Gray shades */
+	  0x00,  0x00,  0x00,  0x10,  0x00,  0x00, /* Black to red */
+	  0x00,  0x00,  0x00,  0x00,  0x10,  0x00, /* Black to green */
+	  0x00,  0x00,  0x00,  0x00,  0x00,  0x10, /* Black to blue */
+	  0x00,  0x00,  0xF0,  0x00,  0x10,  0x00, /* Blue to cyan (blue and green) */
+	  0x00,  0xf0,  0xf0,  0x00,  0x00, -0x10, /* Cyan (blue and green) to green */
+	  0x00,  0xf0,  0x00,  0x10,  0x00,  0x00, /* Green to yellow (red and green)*/
+	  0xf0,  0xf0,  0x00,  0x00, -0x10,  0x00, /* Yellow (red and green) to red */
+	  0xf0,  0x00,  0x00,  0x00,  0x00,  0x10, /* Red to magenta (blue and red) */
+	  0xf0,  0x00,  0xf0, -0x10,  0x00,  0x00, /* Magenta (blue and red) to blue */
+	  0x00,  0x00,  0x00,  0x10,  0x00,  0x10, /* Black to magenta (blue and red)*/
+	  0x00,  0x00,  0x00,  0x00,  0x10,  0x10, /* Black to cyan (blue and green) */
+	  0xf0,  0x00,  0x00,  0x00,  0x10,  0x10, /* Red to white */
+	  0x00,  0xf0,  0x00,  0x10,  0x00,  0x10, /* Green to white */
+	  0x00,  0x00,  0xf0,  0x10,  0x10,  0x00, /* Blue to white */
+};
+
+void e1356fb_init_hardware(void)
+{
+	unsigned char *pRegs = REGISTER_OFFSET;
+	unsigned char *pLUT = LUT8;
+	unsigned char *pseed = lut_base;
+	unsigned char plast[3];
+	int i, j, rgb;
+
+	/* Enable access to SED1356 by setting memory/register select bit to 0. */
+	pRegs[0x001] = 0;
+	udelay(2);
+	/* Disable display outputs during initialization) */
+	pRegs[0x1FC] = 0;
+
+	/* Set the GPIOs to input. Should GPIO bits in register [004] get switched
+	   then the GPIO outputs, according to register [008], are driven low. */
+	pRegs[0x004] = 0;
+	pRegs[0x008] = 0;
+
+	/* Program the LCD panel type and panel timing registers.
+	 *	The horizontal and vertical non-display times have been
+	 *	calculated for a 78 Hz frame rate.
+	 *                                                LCD PCLK
+	 *                          FrameRate = -----------------------------
+	 *                                      (HDP + HNDP) * (VDP/2 + VNDP)
+	 *
+	 *           20,000,000
+	 * = ---------------------------- = 78 Hz
+	 *   (640 + 256) * (480 / 2 + 45)
+	 */
+
+	pRegs[0x10] = 0x1;	/* Memory Clock Configuration Register */
+	pRegs[0x14] = 0x11;	/* LCD Pixel Clock Configuration Register */
+	pRegs[0x18] = 0x1;	/* CRT/TV Pixel Clock Configuration Register */
+	pRegs[0x1c] = 0x1;	/* MediaPlug Clock Configuration Register */
+	pRegs[0x1e] = 0x1;	/* CPU To Memory Wait State Select Register */
+	pRegs[0x20] = 0;	/* Memory Configuration Register */
+	pRegs[0x21] = 0x45;	/* DRAM Refresh Rate Register */
+	pRegs[0x2a] = 0x1;	/* DRAM Timings Control Register 0 */
+	pRegs[0x2b] = 0x1;	/* DRAM Timings Control Register 1 */
+	pRegs[0x30] = 0x1c;	/* Panel Type Register */
+	pRegs[0x31] = 0;	/* MOD Rate Register */
+	pRegs[0x32] = 0x4f;	/* LCD Horizontal Display Width Register */
+	pRegs[0x34] = 0x7;	/* LCD Horizontal Non-Display Period Register */
+	pRegs[0x35] = 0x1;	/* TFT FPLINE Start Position Register */
+	pRegs[0x36] = 0xb;	/* TFT FPLINE Pulse Width Register */
+	pRegs[0x38] = 0xef;	/* LCD Vertical Display Height Register 0 */
+	pRegs[0x39] = 0;	/* LCD Vertical Display Height Register 1 */
+	pRegs[0x3a] = 0x13;	/* LCD Vertical Non-Display Period Register */
+	pRegs[0x3b] = 0xb;	/* TFT FPFRAME Start Position Register */
+	pRegs[0x3c] = 0x1;	/* TFT FPFRAME Pulse Width Register */
+	pRegs[0x40] = 0x5;	/* LCD Display Mode Register */
+	pRegs[0x41] = 0;	/* LCD Miscellaneous Register */
+	pRegs[0x42] = 0;	/* LCD Display Start Address Register 0 */
+	pRegs[0x43] = 0;	/* LCD Display Start Address Register 1 */
+	pRegs[0x44] = 0;	/* LCD Display Start Address Register 2 */
+	pRegs[0x46] = 0x80;	/* LCD Memory Address Offset Register 0 */
+	pRegs[0x47] = 0x2;	/* LCD Memory Address Offset Register 1 */
+	pRegs[0x48] = 0;	/* LCD Pixel Panning Register */
+	pRegs[0x4a] = 0;	/* LCD Display FIFO High Threshold Control Register */
+	pRegs[0x4b] = 0;	/* LCD Display FIFO Low Threshold Control Register */
+	pRegs[0x50] = 0x4f;	/* CRT/TV Horizontal Display Width Register */
+	pRegs[0x52] = 0x13;	/* CRT/TV Horizontal Non-Display Period Register */
+	pRegs[0x53] = 0x1;	/* CRT/TV HRTC Start Position Register */
+	pRegs[0x54] = 0xb;	/* CRT/TV HRTC Pulse Width Register */
+	pRegs[0x56] = 0xdf;	/* CRT/TV Vertical Display Height Register 0 */
+	pRegs[0x57] = 0x1;	/* CRT/TV Vertical Display Height Register 1 */
+	pRegs[0x58] = 0x2b;	/* CRT/TV Vertical Non-Display Period Register */
+	pRegs[0x59] = 0x9;	/* CRT/TV VRTC Start Position Register */
+	pRegs[0x5a] = 0x1;	/* CRT/TV VRTC Pulse Width Register */
+	pRegs[0x5b] = 0x10;	/* TV Output Control Register */
+	pRegs[0x60] = 0x3;	/* CRT/TV Display Mode Register */
+	pRegs[0x62] = 0;	/* CRT/TV Display Start Address Register 0 */
+	pRegs[0x63] = 0;	/* CRT/TV Display Start Address Register 1 */
+	pRegs[0x64] = 0;	/* CRT/TV Display Start Address Register 2 */
+	pRegs[0x66] = 0x40;	/* CRT/TV Memory Address Offset Register 0 */
+	pRegs[0x67] = 0x1;	/* CRT/TV Memory Address Offset Register 1 */
+	pRegs[0x68] = 0;	/* CRT/TV Pixel Panning Register */
+	pRegs[0x6a] = 0;	/* CRT/TV Display FIFO High Threshold Control Register */
+	pRegs[0x6b] = 0;	/* CRT/TV Display FIFO Low Threshold Control Register */
+	pRegs[0x70] = 0;	/* LCD Ink/Cursor Control Register */
+	pRegs[0x71] = 0x1;	/* LCD Ink/Cursor Start Address Register */
+	pRegs[0x72] = 0;	/* LCD Cursor X Position Register 0 */
+	pRegs[0x73] = 0;	/* LCD Cursor X Position Register 1 */
+	pRegs[0x74] = 0;	/* LCD Cursor Y Position Register 0 */
+	pRegs[0x75] = 0;	/* LCD Cursor Y Position Register 1 */
+	pRegs[0x76] = 0;	/* LCD Ink/Cursor Blue Color 0 Register */
+	pRegs[0x77] = 0;	/* LCD Ink/Cursor Green Color 0 Register */
+	pRegs[0x78] = 0;	/* LCD Ink/Cursor Red Color 0 Register */
+	pRegs[0x7a] = 0x1f;	/* LCD Ink/Cursor Blue Color 1 Register */
+	pRegs[0x7b] = 0x3f;	/* LCD Ink/Cursor Green Color 1 Register */
+	pRegs[0x7c] = 0x1f;	/* LCD Ink/Cursor Red Color 1 Register */
+	pRegs[0x7e] = 0;	/* LCD Ink/Cursor FIFO Threshold Register */
+	pRegs[0x80] = 0;	/* CRT/TV Ink/Cursor Control Register */
+	pRegs[0x81] = 0x1;	/* CRT/TV Ink/Cursor Start Address Register */
+	pRegs[0x82] = 0;	/* CRT/TV Cursor X Position Register 0 */
+	pRegs[0x83] = 0;	/* CRT/TV Cursor X Position Register 1 */
+	pRegs[0x84] = 0;	/* CRT/TV Cursor Y Position Register 0 */
+	pRegs[0x85] = 0;	/* CRT/TV Cursor Y Position Register 1 */
+	pRegs[0x86] = 0;	/* CRT/TV Ink/Cursor Blue Color 0 Register */
+	pRegs[0x87] = 0;	/* CRT/TV Ink/Cursor Green Color 0 Register */
+	pRegs[0x88] = 0;	/* CRT/TV Ink/Cursor Red Color 0 Register */
+	pRegs[0x8a] = 0x1f;	/* CRT/TV Ink/Cursor Blue Color 1 Register */
+	pRegs[0x8b] = 0x3f;	/* CRT/TV Ink/Cursor Green Color 1 Register */
+	pRegs[0x8c] = 0x1f;	/* CRT/TV Ink/Cursor Red Color 1 Register */
+	pRegs[0x8e] = 0;	/* CRT/TV Ink/Cursor FIFO Threshold Register */
+
+	/* Set the 2D acceleration (BitBLT) registers to a known state */
+	for (i = 0x100; i <= 0x119; i++)
+		if (i != 0x107 && i != 0x10b && i != 0x10e && i != 0x10f && i != 0x117)
+			pRegs[i] = 0x00;
+
+	/* Program the look-up table to a known state.  */
+	pRegs[0x1E0] = 0x01;	/* Enable the LCD LUT for read/write. */
+	pRegs[0x1E2] = 0;	/* Reset the LUT address. */
+	for (i = 0; i < 16 * 3; i++)
+		pRegs[0x1E4] = *pLUT++;	/* non-regular color template */
+
+	for (i = 0; i < 15; i++) {
+		for (rgb = 0; rgb < 3; rgb++) {
+			plast[rgb] = *pseed++;		/* base color value */
+			pRegs[0x1E4] = plast[rgb];
+		}
+		for (j = 0; j < 15; j++)
+			for (rgb = 0; rgb < 3; rgb++) {
+				plast[rgb] += pseed[rgb];	/* increment through color values*/
+				pRegs[0x1E4] = plast[rgb];
+			}
+		pseed += 3;
+	}
+
+	pRegs[0x1e4] = 0;	/* Look-Up Table Data Register */
+	pRegs[0x1f0] = 0;	/* Power Save Configuration Register */
+	pRegs[0x1f1] = 0;	/* Power Save Status Register */
+	pRegs[0x1f4] = 0;	/* CPU-to-Memory Access Watchdog Timer Register */
+
+	PPSR |= PPC_LDD0;
+
+	mdelay(100);		/* Wait for 100ms */
+	pRegs[0x1F0] = 0;	/* Turn off power save mode */
+	pRegs[0x1F4] = 0;	/* Disable the watchdog timer */
+	pRegs[0x1FC] = 0x01;	/* Disable power save mode, enable display */
+}
+
+int __init e1356fb_init(void)
+{
+	if (fb_get_options("e1356fb", NULL))
+		return -ENODEV;
+		
+	printk("Configuring the Jornada 720 screen...\n");
+
+	fb_info.screen_base = (u_char *) DISP_MEM_OFFSET;
+	fb_info.screen_size = ALLOCATED_FB_MEM_SIZE;
+	memset(&fb_info.var, 0, sizeof(fb_info.var));
+
+	PPSR &= ~(PPC_LDD0 | PPC_LDD1 | PPC_LDD2);
+	PPDR |= PPC_LDD0 | PPC_LDD1 | PPC_LDD2;
+	LCCR3 = 0;
+	LCCR2 = 0;
+	LCCR1 = 0;
+	LCCR0 = 0;
+	DBAR1 = 0;
+	DBAR2 = 0;
+	
+	e1356fb_init_hardware();
+	memset ((unsigned char *)DISP_MEM_OFFSET, 0, ALLOCATED_FB_MEM_SIZE);
+	
+	PPSR |= PPC_LDD1;
+	mdelay(100);	/* delay again */
+	PPSR |= PPC_LDD2;
+	
+	fb_info.fbops		= &e1356fb_ops;
+	fb_info.var		= e1356fb_screeninfo;
+	fb_info.fix		= e1356fb_fix;
+	fb_info.flags		= FBINFO_DEFAULT;
+	
+	fb_info.pseudo_palette	= &pseudo_pal;
+	
+	if (register_framebuffer(&fb_info) < 0)
+		return 1;
+
+	return 0;
+}
+
+module_init(e1356fb_init);
+