hh.org updates
[hh.org.git] / arch / arm / mach-pxa / htcblueangel / blueangel_lcd.c
blobf87303878b8944b1518761c50b4022c20dc6ee0c
1 /*
2 * Hardware definitions for HP iPAQ Handheld Computers
4 * Copyright 2000-2003 Hewlett-Packard Company.
6 * Use consistent with the GNU GPL is permitted,
7 * provided that this copyright notice is
8 * preserved in its entirety in all copies and derived works.
10 * COMPAQ COMPUTER CORPORATION MAKES NO WARRANTIES, EXPRESSED OR IMPLIED,
11 * AS TO THE USEFULNESS OR CORRECTNESS OF THIS CODE OR ITS
12 * FITNESS FOR ANY PARTICULAR PURPOSE.
14 * Author: Jamey Hicks.
16 * History:
18 * 2003-05-14 Joshua Wise Adapted for the HP iPAQ H1900
19 * 2002-08-23 Jamey Hicks Adapted for use with PXA250-based iPAQs
20 * 2001-10-?? Andrew Christian Added support for iPAQ H3800
21 * and abstracted EGPIO interface.
24 #include <linux/module.h>
25 #include <linux/init.h>
26 #include <linux/kernel.h>
27 #include <linux/tty.h>
28 #include <linux/sched.h>
29 #include <linux/delay.h>
30 #include <linux/pm.h>
31 #include <linux/lcd.h>
32 #include <linux/backlight.h>
33 #include <linux/fb.h>
34 #include <video/w100fb.h>
35 #include <linux/platform_device.h>
37 #include <asm/hardware.h>
38 #include <asm/setup.h>
40 #include <asm/mach-types.h>
41 #include <asm/mach/arch.h>
42 #include <asm/arch/htcblueangel-asic.h>
43 #include <asm/arch/pxa-regs.h>
44 #include <asm/arch/pxafb.h>
45 #include "blueangel_lcd.h"
47 #include <linux/soc/asic3_base.h>
49 extern struct platform_device blueangel_asic3;
52 #define BLUEANGEL_ATI_W3200_PHYS PXA_CS2_PHYS
54 extern int blueangel_boardid;
56 static struct lcd_device *blueangel_lcd_device;
57 static int blueangel_lcd_power;
59 static void
60 blueangel_lcd_hw_init_pre(void)
62 printk("blueangel_lcd_hw_init_pre");
63 asic3_set_gpio_out_b (&blueangel_asic3.dev, GPIOB_FL_PWR_ON, GPIOB_FL_PWR_ON);
65 switch (blueangel_boardid)
67 case 4:
68 case 5:
69 asic3_set_gpio_out_b(&blueangel_asic3.dev, GPIOB_LCD_PWR1_ON, 0);
70 mdelay(10);
71 asic3_set_gpio_out_b(&blueangel_asic3.dev, GPIOB_LCD_PWR2_ON, GPIOB_LCD_PWR2_ON);
72 mdelay(1);
73 asic3_set_gpio_out_b(&blueangel_asic3.dev, GPIOB_LCD_PWR3_ON, GPIOB_LCD_PWR3_ON);
74 mdelay(10);
75 asic3_set_gpio_out_b(&blueangel_asic3.dev, GPIOB_LCD_PWR1_ON, GPIOB_LCD_PWR1_ON);
76 break;
77 case 6:
78 asic3_set_gpio_out_b(&blueangel_asic3.dev, GPIOB_LCD_PWR2_ON, GPIOB_LCD_PWR2_ON);
79 asic3_set_gpio_out_c(&blueangel_asic3.dev, GPIOC_LCD_PWR5_ON, GPIOC_LCD_PWR5_ON);
80 udelay(600);
81 break;
85 static void
86 blueangel_lcd_hw_init_post(void)
88 printk("blueangel_lcd_hw_init_post");
90 switch (blueangel_boardid)
92 case 6:
93 asic3_set_gpio_out_b(&blueangel_asic3.dev, GPIOB_LCD_PWR1_ON, GPIOB_LCD_PWR1_ON);
94 mdelay(10);
95 asic3_set_gpio_out_b(&blueangel_asic3.dev, GPIOB_LCD_PWR3_ON, GPIOB_LCD_PWR3_ON);
96 mdelay(10);
97 asic3_set_gpio_out_c(&blueangel_asic3.dev, GPIOC_LCD_PWR4_ON, GPIOC_LCD_PWR4_ON);
98 mdelay(20);
102 static void
103 blueangel_lcd_hw_off(void)
105 printk("blueangel_lcd_hw_off\n");
106 asic3_set_gpio_out_b (&blueangel_asic3.dev, GPIOB_FL_PWR_ON, 0);
107 switch (blueangel_boardid)
109 case 6:
110 asic3_set_gpio_out_b(&blueangel_asic3.dev, GPIOB_LCD_PWR1_ON, 0);
111 asic3_set_gpio_out_c(&blueangel_asic3.dev, GPIOC_LCD_PWR4_ON, 0);
112 asic3_set_gpio_out_b(&blueangel_asic3.dev, GPIOB_LCD_PWR3_ON, 0);
113 asic3_set_gpio_out_b(&blueangel_asic3.dev, GPIOB_LCD_PWR2_ON, 0);
114 asic3_set_gpio_out_c(&blueangel_asic3.dev, GPIOC_LCD_PWR5_ON, 0);
115 break;
116 case 4:
117 case 5:
118 mdelay(5);
119 asic3_set_gpio_out_b(&blueangel_asic3.dev, GPIOB_LCD_PWR1_ON, 0);
120 mdelay(2);
121 asic3_set_gpio_out_b(&blueangel_asic3.dev, GPIOB_LCD_PWR3_ON, 0);
122 mdelay(2);
123 asic3_set_gpio_out_b(&blueangel_asic3.dev, GPIOB_LCD_PWR2_ON, 0);
124 break;
128 static int blueangel_lcd_set_power( struct lcd_device *ld, int level)
130 // printk("FB_BLANK_UNBLANK %d FB_BLANK_NORMAL %d\n", FB_BLANK_UNBLANK, FB_BLANK_NORMAL);
131 // printk("FB_BLANK_VSYNC_SUSPEND %d FB_BLANK_HSYNC_SUSPEND %d\n", FB_BLANK_VSYNC_SUSPEND, FB_BLANK_HSYNC_SUSPEND);
132 // printk("FB_BLANK_POWERDOWN %d\n", FB_BLANK_POWERDOWN);
133 // printk("blueangel LCD power %d\n",level);
134 switch (level) {
135 case FB_BLANK_UNBLANK:
136 case FB_BLANK_NORMAL:
137 /* no - don't do it! you need to re-initialise the w100
138 * chip. as well. sorry.*/
139 #if 1
140 blueangel_lcd_hw_init_pre();
141 blueangel_lcd_hw_init_post();
142 #endif
143 break;
144 case FB_BLANK_VSYNC_SUSPEND:
145 case FB_BLANK_HSYNC_SUSPEND:
146 break;
147 case FB_BLANK_POWERDOWN:
148 blueangel_lcd_hw_off();
149 break;
151 blueangel_lcd_power=level;
152 return 0;
155 static int blueangel_lcd_get_power(struct lcd_device *ld)
157 printk("blueangel_lcd_get_power\n");
158 return blueangel_lcd_power;
161 static struct lcd_properties blueangel_lcd_props = {
162 .owner = THIS_MODULE,
163 .set_power = blueangel_lcd_set_power,
164 .get_power = blueangel_lcd_get_power,
167 static void
168 blueangel_lcd_suspend(struct w100fb_par *wfb)
170 #if 0
171 ati_gpios[0] = w100fb_gpio_read(W100_GPIO_PORT_A);
172 ati_gpios[1] = w100fb_gpcntl_read(W100_GPIO_PORT_A);
173 ati_gpios[2] = w100fb_gpio_read(W100_GPIO_PORT_B);
174 ati_gpios[3] = w100fb_gpcntl_read(W100_GPIO_PORT_B);
175 w100fb_gpio_write(W100_GPIO_PORT_A, 0xDFE00000 );
176 w100fb_gpcntl_write(W100_GPIO_PORT_A, 0xFFFF0000 );
177 w100fb_gpio_write(W100_GPIO_PORT_B, 0x00000000 );
178 w100fb_gpcntl_write(W100_GPIO_PORT_B, 0xFFFFFFFF );
179 save_bright = PWM_PWDUTY1;
180 #endif
182 blueangel_lcd_hw_off();
185 static void
186 blueangel_lcd_resume_pre(struct w100fb_par *wfb)
188 #if 0
189 w100fb_gpio_write(W100_GPIO_PORT_A, ati_gpios[0] );
190 w100fb_gpcntl_write(W100_GPIO_PORT_A, ati_gpios[1] );
191 w100fb_gpio_write(W100_GPIO_PORT_B, ati_gpios[2] );
192 w100fb_gpcntl_write(W100_GPIO_PORT_B, ati_gpios[3] );
193 lcd_hw_init();
194 LCD_SET_BRIGHT( save_bright );
195 #endif
196 blueangel_lcd_hw_init_pre();
199 static void
200 blueangel_lcd_resume_post(struct w100fb_par *wfb)
202 blueangel_lcd_hw_init_post();
205 static void
206 blueangel_lcd_w100_resume(struct w100fb_par *wfb) {
207 blueangel_lcd_resume_pre(wfb);
208 msleep(30);
209 blueangel_lcd_resume_post(wfb);
213 struct w100_tg_info blueangel_tg_info = {
214 .suspend = blueangel_lcd_suspend,
215 .resume = blueangel_lcd_w100_resume,
216 // .resume_pre = blueangel_lcd_resume_pre,
217 // .resume_post = blueangel_lcd_resume_post,
220 static struct w100_gen_regs blueangel_w100_regs = {
221 .lcd_format = 0x00000003,
222 .lcdd_cntl1 = 0x00000000,
223 .lcdd_cntl2 = 0x0003ffff,
224 .genlcd_cntl1 = 0x00fff003, // 0x00fff003
225 .genlcd_cntl2 = 0x00000003,
226 .genlcd_cntl3 = 0x000102aa,
229 static struct w100_mode blueangel_w100_modes_4[] = {
231 .xres = 240,
232 .yres = 320,
233 .left_margin = 0,
234 .right_margin = 31,
235 .upper_margin = 15,
236 .lower_margin = 0,
237 .crtc_ss = 0x80150014,
238 .crtc_ls = 0xa0fb00f7,
239 .crtc_gs = 0xc0080007,
240 .crtc_vpos_gs = 0x80007,
241 .crtc_rev = 0x0000000a,
242 .crtc_dclk = 0x81700030,
243 .crtc_gclk = 0x8015010f,
244 .crtc_goe = 0x00000000,
245 .pll_freq = 80,
246 .pixclk_divider = 15,
247 .pixclk_divider_rotated = 15,
248 .pixclk_src = CLK_SRC_PLL,
249 .sysclk_divider = 0,
250 .sysclk_src = CLK_SRC_PLL,
254 static struct w100_mode blueangel_w100_modes_5[] = {
256 .xres = 240,
257 .yres = 320,
258 .left_margin = 0,
259 .right_margin = 31,
260 .upper_margin = 15,
261 .lower_margin = 0,
262 .crtc_ss = 0x80150014,
263 .crtc_ls = 0xa0020110,
264 .crtc_gs = 0xc0890088,
265 .crtc_vpos_gs = 0x01450144,
266 .crtc_rev = 0x0000000a,
267 .crtc_dclk = 0xa1700030,
268 .crtc_gclk = 0x8015010f,
269 .crtc_goe = 0x00000000,
270 .pll_freq = 57,
271 .pixclk_divider = 4,
272 .pixclk_divider_rotated = 4,
273 .pixclk_src = CLK_SRC_PLL,
274 .sysclk_divider = 0,
275 .sysclk_src = CLK_SRC_PLL,
279 static struct w100_mode blueangel_w100_modes_6[] = {
281 .xres = 240,
282 .yres = 320,
283 .left_margin = 20,
284 .right_margin = 19,
285 .upper_margin = 3,
286 .lower_margin = 2,
287 .crtc_ss = 0x80150014,
288 .crtc_ls = 0xa0020110,
289 .crtc_gs = 0xc0890088,
290 .crtc_vpos_gs = 0x01450144,
291 .crtc_rev = 0x0000000a,
292 .crtc_dclk = 0xa1700030,
293 .crtc_gclk = 0x8015010f,
294 .crtc_goe = 0x00000000,
295 .pll_freq = 57,
296 .pixclk_divider = 4,
297 .pixclk_divider_rotated = 4,
298 .pixclk_src = CLK_SRC_PLL,
299 .sysclk_divider = 0,
300 .sysclk_src = CLK_SRC_PLL,
304 struct w100_mem_info blueangel_mem_info = {
305 .ext_cntl = 0x01040010,
306 .sdram_mode_reg = 0x00250000,
307 .ext_timing_cntl = 0x00001545,
308 .io_cntl = 0x7ddd7333,
309 .size = 0x3fffff,
312 struct w100_bm_mem_info blueangel_bm_mem_info = {
313 .ext_mem_bw = 0xfbfd2d07,
314 .offset = 0x000c0000,
315 .ext_timing_ctl = 0x00043f7f,
316 .ext_cntl = 0x00000010,
317 .mode_reg = 0x006c0000,
318 .io_cntl = 0x000e0fff,
319 .config = 0x08300562,
322 static struct w100_gpio_regs blueangel_w100_gpio_info = {
323 .init_data1 = 0x00000000, // GPIO_DATA
324 .gpio_dir1 = 0xe0000000, // GPIO_CNTL1
325 .gpio_oe1 = 0x003c2000, // GPIO_CNTL2
326 .init_data2 = 0x00000000, // GPIO_DATA2
327 .gpio_dir2 = 0x00000000, // GPIO_CNTL3
328 .gpio_oe2 = 0x00000000, // GPIO_CNTL4
331 static struct w100fb_mach_info blueangel_fb_info = {
332 .tg = &blueangel_tg_info,
333 .mem = &blueangel_mem_info,
334 .bm_mem = &blueangel_bm_mem_info,
335 .gpio = &blueangel_w100_gpio_info,
336 .regs = &blueangel_w100_regs,
337 .modelist = blueangel_w100_modes_6,
338 .num_modes = 1,
339 .xtal_freq = 16000000,
343 static struct resource blueangel_fb_resources[] = {
344 [0] = {
345 .start = BLUEANGEL_ATI_W3200_PHYS,
346 .end = BLUEANGEL_ATI_W3200_PHYS + 0x00ffffff,
347 .flags = IORESOURCE_MEM,
351 static struct platform_device blueangel_fb_device = {
352 .name = "w100fb",
353 .id = 0,
354 .dev = {
355 .platform_data = &blueangel_fb_info,
357 .num_resources = ARRAY_SIZE( blueangel_fb_resources ),
358 .resource = blueangel_fb_resources,
361 static int
362 blueangel_lcd_probe( struct device *dev )
364 int ret;
366 printk("in blueangel_lcd_probe\n");
368 blueangel_lcd_device = lcd_device_register("w100fb", (void *)&blueangel_fb_info, &blueangel_lcd_props);
369 if (IS_ERR(blueangel_lcd_device)) {
370 return PTR_ERR(blueangel_lcd_device);
373 ret = platform_device_register( &blueangel_fb_device );
374 // TODO:
376 return ret;
379 static int
380 blueangel_lcd_remove( struct device *dev )
382 lcd_device_unregister (blueangel_lcd_device);
383 platform_device_unregister(&blueangel_fb_device);
384 return 0;
387 static int
388 blueangel_lcd_resume(struct device *dev) {
389 blueangel_lcd_hw_init_pre();
390 msleep(30);
391 blueangel_lcd_hw_init_post();
392 return 0;
396 struct platform_driver blueangel_lcd_driver = {
397 .driver = {
398 .name = "blueangel-lcd",
399 .bus = &platform_bus_type,
400 .probe = blueangel_lcd_probe,
401 .remove = blueangel_lcd_remove,
402 .resume = blueangel_lcd_resume,
407 int __init
408 blueangel_lcd_init (void)
410 printk("blueangel_lcd_init\n");
411 if (! machine_is_blueangel())
412 return -ENODEV;
414 switch (blueangel_boardid)
416 case 0x4:
417 blueangel_fb_info.modelist=blueangel_w100_modes_4;
418 break;
419 case 0x5:
420 blueangel_fb_info.modelist=blueangel_w100_modes_5;
421 break;
422 case 0x6:
423 blueangel_fb_info.modelist=blueangel_w100_modes_6;
424 break;
425 default:
426 printk("blueangel lcd_init: unknown boardid=%d. Using 0x6\n",blueangel_boardid);
427 blueangel_fb_info.modelist=blueangel_w100_modes_6;
430 return platform_driver_register( &blueangel_lcd_driver );
435 void __exit
436 blueangel_lcd_exit (void)
438 platform_driver_unregister( &blueangel_lcd_driver );
441 module_init (blueangel_lcd_init);
442 module_exit (blueangel_lcd_exit);
443 MODULE_LICENSE("GPL");