Merge ../linus
[linux-2.6] / arch / arm / mach-lh7a40x / clcd.c
1 /*
2  *  arch/arm/mach-lh7a40x/clcd.c
3  *
4  *  Copyright (C) 2004 Marc Singer
5  *
6  *  This program is free software; you can redistribute it and/or
7  *  modify it under the terms of the GNU General Public License
8  *  version 2 as published by the Free Software Foundation.
9  *
10  */
11 #include <linux/config.h>
12 #include <linux/init.h>
13 #include <linux/device.h>
14 #include <linux/dma-mapping.h>
15 #include <linux/sysdev.h>
16 #include <linux/interrupt.h>
17
18 //#include <linux/module.h>
19 //#include <linux/time.h>
20 //#include <asm/hardware.h>
21
22 //#include <asm/mach/time.h>
23 #include <asm/irq.h>
24 #include <asm/mach/irq.h>
25
26 #include <asm/system.h>
27 #include <asm/hardware.h>
28 #include <linux/amba/bus.h>
29 #include <linux/amba/clcd.h>
30
31 #define HRTFTC_HRSETUP          __REG(HRTFTC_PHYS + 0x00)
32 #define HRTFTC_HRCON            __REG(HRTFTC_PHYS + 0x04)
33 #define HRTFTC_HRTIMING1        __REG(HRTFTC_PHYS + 0x08)
34 #define HRTFTC_HRTIMING2        __REG(HRTFTC_PHYS + 0x0c)
35
36 #define ALI_SETUP               __REG(ALI_PHYS + 0x00)
37 #define ALI_CONTROL             __REG(ALI_PHYS + 0x04)
38 #define ALI_TIMING1             __REG(ALI_PHYS + 0x08)
39 #define ALI_TIMING2             __REG(ALI_PHYS + 0x0c)
40
41 #include "lcd-panel.h"
42
43 static void lh7a40x_clcd_disable (struct clcd_fb *fb)
44 {
45 #if defined (CONFIG_MACH_LPD7A400)
46         CPLD_CONTROL &= ~(1<<1);        /* Disable LCD Vee */
47 #endif
48
49 #if defined (CONFIG_MACH_LPD7A404)
50         GPIO_PCD  &= ~(1<<3);           /* Disable LCD Vee */
51 #endif
52
53 #if defined (CONFIG_ARCH_LH7A400)
54         HRTFTC_HRSETUP &= ~(1<<13);     /* Disable HRTFT controller */
55 #endif
56
57 #if defined (CONFIG_ARCH_LH7A404)
58         ALI_SETUP &= ~(1<<13);          /* Disable ALI */
59 #endif
60 }
61
62 static void lh7a40x_clcd_enable (struct clcd_fb *fb)
63 {
64         struct clcd_panel_extra* extra
65                 = (struct clcd_panel_extra*) fb->board_data;
66
67 #if defined (CONFIG_MACH_LPD7A400)
68         CPLD_CONTROL |= (1<<1);         /* Enable LCD Vee */
69 #endif
70
71 #if defined (CONFIG_MACH_LPD7A404)
72         GPIO_PCDD &= ~(1<<3);           /* Enable LCD Vee */
73         GPIO_PCD  |=  (1<<3);
74 #endif
75
76 #if defined (CONFIG_ARCH_LH7A400)
77
78         if (extra) {
79                 HRTFTC_HRSETUP
80                         = (1 << 13)
81                         | ((fb->fb.var.xres - 1) << 4)
82                         | 0xc
83                         | (extra->hrmode ? 1 : 0);
84                 HRTFTC_HRCON
85                         = ((extra->clsen ? 1 : 0) << 1)
86                         | ((extra->spsen ? 1 : 0) << 0);
87                 HRTFTC_HRTIMING1
88                         = (extra->pcdel << 8)
89                         | (extra->revdel << 4)
90                         | (extra->lpdel << 0);
91                 HRTFTC_HRTIMING2
92                         = (extra->spldel << 9)
93                         | (extra->pc2del << 0);
94         }
95         else
96                 HRTFTC_HRSETUP
97                         = (1 << 13)
98                         | 0xc;
99 #endif
100
101 #if defined (CONFIG_ARCH_LH7A404)
102
103         if (extra) {
104                 ALI_SETUP
105                         = (1 << 13)
106                         | ((fb->fb.var.xres - 1) << 4)
107                         | 0xc
108                         | (extra->hrmode ? 1 : 0);
109                 ALI_CONTROL
110                         = ((extra->clsen ? 1 : 0) << 1)
111                         | ((extra->spsen ? 1 : 0) << 0);
112                 ALI_TIMING1
113                         = (extra->pcdel << 8)
114                         | (extra->revdel << 4)
115                         | (extra->lpdel << 0);
116                 ALI_TIMING2
117                         = (extra->spldel << 9)
118                         | (extra->pc2del << 0);
119         }
120         else
121                 ALI_SETUP
122                         = (1 << 13)
123                         | 0xc;
124 #endif
125
126 }
127
128 #define FRAMESIZE(s) (((s) + PAGE_SIZE - 1)&PAGE_MASK)
129
130 static int lh7a40x_clcd_setup (struct clcd_fb *fb)
131 {
132         dma_addr_t dma;
133         u32 len = FRAMESIZE (lcd_panel.mode.xres*lcd_panel.mode.yres
134                              *(lcd_panel.bpp/8));
135
136         fb->panel = &lcd_panel;
137
138                 /* Enforce the sync polarity defaults */
139         if (!(fb->panel->tim2 & TIM2_IHS))
140                 fb->fb.var.sync |= FB_SYNC_HOR_HIGH_ACT;
141         if (!(fb->panel->tim2 & TIM2_IVS))
142                 fb->fb.var.sync |= FB_SYNC_VERT_HIGH_ACT;
143
144 #if defined (HAS_LCD_PANEL_EXTRA)
145         fb->board_data = &lcd_panel_extra;
146 #endif
147
148         fb->fb.screen_base
149                 = dma_alloc_writecombine (&fb->dev->dev, len,
150                                           &dma, GFP_KERNEL);
151         printk ("CLCD: LCD setup fb virt 0x%p phys 0x%p l %x io 0x%p \n",
152                 fb->fb.screen_base, (void*) dma, len,
153                 (void*) io_p2v (CLCDC_PHYS));
154         printk ("CLCD: pixclock %d\n", lcd_panel.mode.pixclock);
155
156         if (!fb->fb.screen_base) {
157                 printk(KERN_ERR "CLCD: unable to map framebuffer\n");
158                 return -ENOMEM;
159         }
160
161 #if defined (USE_RGB555)
162         fb->fb.var.green.length = 5; /* Panel uses RGB 5:5:5 */
163 #endif
164
165         fb->fb.fix.smem_start = dma;
166         fb->fb.fix.smem_len = len;
167
168                 /* Drive PE4 high to prevent CPLD crash */
169         GPIO_PEDD |= (1<<4);
170         GPIO_PED  |= (1<<4);
171
172         GPIO_PINMUX |= (1<<1) | (1<<0); /* LCDVD[15:4] */
173
174 //      fb->fb.fbops->fb_check_var (&fb->fb.var, &fb->fb);
175 //      fb->fb.fbops->fb_set_par (&fb->fb);
176
177         return 0;
178 }
179
180 static int lh7a40x_clcd_mmap (struct clcd_fb *fb, struct vm_area_struct *vma)
181 {
182         return dma_mmap_writecombine(&fb->dev->dev, vma,
183                                      fb->fb.screen_base,
184                                      fb->fb.fix.smem_start,
185                                      fb->fb.fix.smem_len);
186 }
187
188 static void lh7a40x_clcd_remove (struct clcd_fb *fb)
189 {
190         dma_free_writecombine (&fb->dev->dev, fb->fb.fix.smem_len,
191                                fb->fb.screen_base, fb->fb.fix.smem_start);
192 }
193
194 static struct clcd_board clcd_platform_data = {
195         .name           = "lh7a40x FB",
196         .check          = clcdfb_check,
197         .decode         = clcdfb_decode,
198         .enable         = lh7a40x_clcd_enable,
199         .setup          = lh7a40x_clcd_setup,
200         .mmap           = lh7a40x_clcd_mmap,
201         .remove         = lh7a40x_clcd_remove,
202         .disable        = lh7a40x_clcd_disable,
203 };
204
205 #define IRQ_CLCDC (IRQ_LCDINTR)
206
207 #define AMBA_DEVICE(name,busid,base,plat,pid)                   \
208 static struct amba_device name##_device = {                     \
209         .dev = {                                                \
210                 .coherent_dma_mask = ~0,                        \
211                 .bus_id = busid,                                \
212                 .platform_data = plat,                          \
213                 },                                              \
214         .res = {                                                \
215                 .start  = base##_PHYS,                          \
216                 .end    = (base##_PHYS) + (4*1024) - 1,         \
217                 .flags  = IORESOURCE_MEM,                       \
218                 },                                              \
219         .dma_mask       = ~0,                                   \
220         .irq            = { IRQ_##base, },                      \
221         /* .dma         = base##_DMA,*/                         \
222         .periphid = pid,                                        \
223 }
224
225 AMBA_DEVICE(clcd,  "cldc-lh7a40x",  CLCDC,     &clcd_platform_data, 0x41110);
226
227 static struct amba_device *amba_devs[] __initdata = {
228         &clcd_device,
229 };
230
231 void __init lh7a40x_clcd_init (void)
232 {
233         int i;
234         int result;
235         printk ("CLCD: registering amba devices\n");
236         for (i = 0; i < ARRAY_SIZE(amba_devs); i++) {
237                 struct amba_device *d = amba_devs[i];
238                 result = amba_device_register(d, &iomem_resource);
239                 printk ("  %d -> %d\n", i ,result);
240         }
241 }