This commit was manufactured by cvs2svn to create branch 'vserver'.
[linux-2.6.git] / arch / arm / mach-lh7a40x / clcd.c
diff --git a/arch/arm/mach-lh7a40x/clcd.c b/arch/arm/mach-lh7a40x/clcd.c
new file mode 100644 (file)
index 0000000..1992db4
--- /dev/null
@@ -0,0 +1,241 @@
+/*
+ *  arch/arm/mach-lh7a40x/clcd.c
+ *
+ *  Copyright (C) 2004 Marc Singer
+ *
+ *  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.
+ *
+ */
+
+#include <linux/init.h>
+#include <linux/device.h>
+#include <linux/dma-mapping.h>
+#include <linux/sysdev.h>
+#include <linux/interrupt.h>
+
+//#include <linux/module.h>
+//#include <linux/time.h>
+//#include <asm/hardware.h>
+
+//#include <asm/mach/time.h>
+#include <asm/irq.h>
+#include <asm/mach/irq.h>
+
+#include <asm/system.h>
+#include <asm/hardware.h>
+#include <linux/amba/bus.h>
+#include <linux/amba/clcd.h>
+
+#define HRTFTC_HRSETUP         __REG(HRTFTC_PHYS + 0x00)
+#define HRTFTC_HRCON           __REG(HRTFTC_PHYS + 0x04)
+#define HRTFTC_HRTIMING1       __REG(HRTFTC_PHYS + 0x08)
+#define HRTFTC_HRTIMING2       __REG(HRTFTC_PHYS + 0x0c)
+
+#define ALI_SETUP              __REG(ALI_PHYS + 0x00)
+#define ALI_CONTROL            __REG(ALI_PHYS + 0x04)
+#define ALI_TIMING1            __REG(ALI_PHYS + 0x08)
+#define ALI_TIMING2            __REG(ALI_PHYS + 0x0c)
+
+#include "lcd-panel.h"
+
+static void lh7a40x_clcd_disable (struct clcd_fb *fb)
+{
+#if defined (CONFIG_MACH_LPD7A400)
+       CPLD_CONTROL &= ~(1<<1);        /* Disable LCD Vee */
+#endif
+
+#if defined (CONFIG_MACH_LPD7A404)
+       GPIO_PCD  &= ~(1<<3);           /* Disable LCD Vee */
+#endif
+
+#if defined (CONFIG_ARCH_LH7A400)
+       HRTFTC_HRSETUP &= ~(1<<13);     /* Disable HRTFT controller */
+#endif
+
+#if defined (CONFIG_ARCH_LH7A404)
+       ALI_SETUP &= ~(1<<13);          /* Disable ALI */
+#endif
+}
+
+static void lh7a40x_clcd_enable (struct clcd_fb *fb)
+{
+       struct clcd_panel_extra* extra
+               = (struct clcd_panel_extra*) fb->board_data;
+
+#if defined (CONFIG_MACH_LPD7A400)
+       CPLD_CONTROL |= (1<<1);         /* Enable LCD Vee */
+#endif
+
+#if defined (CONFIG_MACH_LPD7A404)
+       GPIO_PCDD &= ~(1<<3);           /* Enable LCD Vee */
+       GPIO_PCD  |=  (1<<3);
+#endif
+
+#if defined (CONFIG_ARCH_LH7A400)
+
+       if (extra) {
+               HRTFTC_HRSETUP
+                       = (1 << 13)
+                       | ((fb->fb.var.xres - 1) << 4)
+                       | 0xc
+                       | (extra->hrmode ? 1 : 0);
+               HRTFTC_HRCON
+                       = ((extra->clsen ? 1 : 0) << 1)
+                       | ((extra->spsen ? 1 : 0) << 0);
+               HRTFTC_HRTIMING1
+                       = (extra->pcdel << 8)
+                       | (extra->revdel << 4)
+                       | (extra->lpdel << 0);
+               HRTFTC_HRTIMING2
+                       = (extra->spldel << 9)
+                       | (extra->pc2del << 0);
+       }
+       else
+               HRTFTC_HRSETUP
+                       = (1 << 13)
+                       | 0xc;
+#endif
+
+#if defined (CONFIG_ARCH_LH7A404)
+
+       if (extra) {
+               ALI_SETUP
+                       = (1 << 13)
+                       | ((fb->fb.var.xres - 1) << 4)
+                       | 0xc
+                       | (extra->hrmode ? 1 : 0);
+               ALI_CONTROL
+                       = ((extra->clsen ? 1 : 0) << 1)
+                       | ((extra->spsen ? 1 : 0) << 0);
+               ALI_TIMING1
+                       = (extra->pcdel << 8)
+                       | (extra->revdel << 4)
+                       | (extra->lpdel << 0);
+               ALI_TIMING2
+                       = (extra->spldel << 9)
+                       | (extra->pc2del << 0);
+       }
+       else
+               ALI_SETUP
+                       = (1 << 13)
+                       | 0xc;
+#endif
+
+}
+
+#define FRAMESIZE(s) (((s) + PAGE_SIZE - 1)&PAGE_MASK)
+
+static int lh7a40x_clcd_setup (struct clcd_fb *fb)
+{
+       dma_addr_t dma;
+       u32 len = FRAMESIZE (lcd_panel.mode.xres*lcd_panel.mode.yres
+                            *(lcd_panel.bpp/8));
+
+       fb->panel = &lcd_panel;
+
+               /* Enforce the sync polarity defaults */
+       if (!(fb->panel->tim2 & TIM2_IHS))
+               fb->fb.var.sync |= FB_SYNC_HOR_HIGH_ACT;
+       if (!(fb->panel->tim2 & TIM2_IVS))
+               fb->fb.var.sync |= FB_SYNC_VERT_HIGH_ACT;
+
+#if defined (HAS_LCD_PANEL_EXTRA)
+       fb->board_data = &lcd_panel_extra;
+#endif
+
+       fb->fb.screen_base
+               = dma_alloc_writecombine (&fb->dev->dev, len,
+                                         &dma, GFP_KERNEL);
+       printk ("CLCD: LCD setup fb virt 0x%p phys 0x%p l %x io 0x%p \n",
+               fb->fb.screen_base, (void*) dma, len,
+               (void*) io_p2v (CLCDC_PHYS));
+       printk ("CLCD: pixclock %d\n", lcd_panel.mode.pixclock);
+
+       if (!fb->fb.screen_base) {
+               printk(KERN_ERR "CLCD: unable to map framebuffer\n");
+               return -ENOMEM;
+       }
+
+#if defined (USE_RGB555)
+       fb->fb.var.green.length = 5; /* Panel uses RGB 5:5:5 */
+#endif
+
+       fb->fb.fix.smem_start = dma;
+       fb->fb.fix.smem_len = len;
+
+               /* Drive PE4 high to prevent CPLD crash */
+       GPIO_PEDD |= (1<<4);
+       GPIO_PED  |= (1<<4);
+
+       GPIO_PINMUX |= (1<<1) | (1<<0); /* LCDVD[15:4] */
+
+//     fb->fb.fbops->fb_check_var (&fb->fb.var, &fb->fb);
+//     fb->fb.fbops->fb_set_par (&fb->fb);
+
+       return 0;
+}
+
+static int lh7a40x_clcd_mmap (struct clcd_fb *fb, struct vm_area_struct *vma)
+{
+       return dma_mmap_writecombine(&fb->dev->dev, vma,
+                                    fb->fb.screen_base,
+                                    fb->fb.fix.smem_start,
+                                    fb->fb.fix.smem_len);
+}
+
+static void lh7a40x_clcd_remove (struct clcd_fb *fb)
+{
+       dma_free_writecombine (&fb->dev->dev, fb->fb.fix.smem_len,
+                              fb->fb.screen_base, fb->fb.fix.smem_start);
+}
+
+static struct clcd_board clcd_platform_data = {
+       .name           = "lh7a40x FB",
+       .check          = clcdfb_check,
+       .decode         = clcdfb_decode,
+       .enable         = lh7a40x_clcd_enable,
+       .setup          = lh7a40x_clcd_setup,
+       .mmap           = lh7a40x_clcd_mmap,
+       .remove         = lh7a40x_clcd_remove,
+       .disable        = lh7a40x_clcd_disable,
+};
+
+#define IRQ_CLCDC (IRQ_LCDINTR)
+
+#define AMBA_DEVICE(name,busid,base,plat,pid)                  \
+static struct amba_device name##_device = {                    \
+       .dev = {                                                \
+               .coherent_dma_mask = ~0,                        \
+               .bus_id = busid,                                \
+               .platform_data = plat,                          \
+               },                                              \
+       .res = {                                                \
+               .start  = base##_PHYS,                          \
+               .end    = (base##_PHYS) + (4*1024) - 1,         \
+               .flags  = IORESOURCE_MEM,                       \
+               },                                              \
+       .dma_mask       = ~0,                                   \
+       .irq            = { IRQ_##base, },                      \
+       /* .dma         = base##_DMA,*/                         \
+       .periphid = pid,                                        \
+}
+
+AMBA_DEVICE(clcd,  "cldc-lh7a40x",  CLCDC,     &clcd_platform_data, 0x41110);
+
+static struct amba_device *amba_devs[] __initdata = {
+       &clcd_device,
+};
+
+void __init lh7a40x_clcd_init (void)
+{
+       int i;
+       int result;
+       printk ("CLCD: registering amba devices\n");
+       for (i = 0; i < ARRAY_SIZE(amba_devs); i++) {
+               struct amba_device *d = amba_devs[i];
+               result = amba_device_register(d, &iomem_resource);
+               printk ("  %d -> %d\n", i ,result);
+       }
+}