--- 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include + +#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); +