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