hh.org updates
[hh.org.git] / arch / arm / mach-pxa / hx4700 / hx4700_lcd.c
blob8ebca1abf6f49e452bb89f625d7d7cded1c943f4
1 /*
2 * LCD support for iPAQ HX4700
4 * Copyright (c) 2005 Ian Molton
5 * Copyright (c) 2005 SDG Systems, LLC
7 * This file is subject to the terms and conditions of the GNU General Public
8 * License. See the file COPYING in the main directory of this archive for
9 * more details.
11 * 04-Jan-2005 Todd Blumer <todd@sdgsystems.com>
12 * Developed from iPAQ H5400
13 * 11-Mar-2005 Ian Molton <spyro@f2s.com>
15 #include <linux/init.h>
16 #include <linux/kernel.h>
17 #include <linux/platform_device.h>
18 #include <linux/lcd.h>
19 #include <linux/fb.h>
20 #include <linux/err.h>
21 #include <linux/delay.h>
23 #include <video/w100fb.h>
25 #include <asm/mach-types.h>
26 #include <asm/hardware.h>
27 #include <asm/mach/arch.h>
29 #include <asm/arch/hx4700-gpio.h>
30 #include <asm/arch/pxa-regs.h>
32 /* ATI Imageon 3220 Graphics */
33 #define HX4700_ATI_W3220_PHYS PXA_CS2_PHYS
35 static int lcd_power;
37 static void
38 lcd_hw_init( void )
40 // printk( KERN_NOTICE "LCD init: clear values\n" );
41 SET_HX4700_GPIO( LCD_SQN, 1 );
42 SET_HX4700_GPIO( LCD_LVDD_3V3_ON, 0 );
43 SET_HX4700_GPIO( LCD_AVDD_3V3_ON, 0 );
44 SET_HX4700_GPIO( LCD_SLIN1, 0 );
45 SET_HX4700_GPIO( LCD_RESET_N, 0 );
46 mdelay(10);
47 SET_HX4700_GPIO( LCD_PC1, 0 );
48 SET_HX4700_GPIO( LCD_LVDD_3V3_ON, 0 );
49 mdelay(20);
51 // printk( KERN_NOTICE "LCD init: set values\n" );
52 SET_HX4700_GPIO( LCD_LVDD_3V3_ON, 1 );
53 mdelay(5);
54 SET_HX4700_GPIO( LCD_AVDD_3V3_ON, 1 );
55 // init w3220 regs?
57 mdelay(5);
58 SET_HX4700_GPIO( LCD_SLIN1, 1 );
59 mdelay(10);
60 SET_HX4700_GPIO( LCD_RESET_N, 1 );
61 mdelay(10);
62 SET_HX4700_GPIO( LCD_PC1, 1 );
63 mdelay(10);
64 SET_HX4700_GPIO( LCD_N2V7_7V3_ON, 1 );
67 static void
68 lcd_hw_off( void )
70 SET_HX4700_GPIO( LCD_PC1, 0 );
71 SET_HX4700_GPIO( LCD_RESET_N, 0 );
72 mdelay(10);
73 SET_HX4700_GPIO( LCD_N2V7_7V3_ON, 0 );
74 mdelay(10);
75 SET_HX4700_GPIO( LCD_AVDD_3V3_ON, 0 );
76 mdelay(10);
77 SET_HX4700_GPIO( LCD_LVDD_3V3_ON, 0 );
80 static int
81 hx4700_lcd_set_power( struct lcd_device *lm, int level )
83 switch (level) {
84 case FB_BLANK_UNBLANK:
85 case FB_BLANK_NORMAL:
86 lcd_hw_init();
87 break;
88 case FB_BLANK_VSYNC_SUSPEND:
89 case FB_BLANK_HSYNC_SUSPEND:
90 break;
91 case FB_BLANK_POWERDOWN:
92 lcd_hw_off();
93 break;
95 lcd_power = level;
96 return 0;
99 static int
100 hx4700_lcd_get_power( struct lcd_device *lm )
102 return lcd_power;
105 static struct lcd_properties w3220_fb0_lcd = {
106 .owner = THIS_MODULE,
107 .get_power = hx4700_lcd_get_power,
108 .set_power = hx4700_lcd_set_power,
111 static struct lcd_device *atifb_lcd_dev;
113 #ifdef CONFIG_PM
115 unsigned long ati_gpios[4];
117 static void
118 hx4700_lcd_suspend( struct w100fb_par *wfb )
120 ati_gpios[0] = w100fb_gpio_read(W100_GPIO_PORT_A);
121 ati_gpios[1] = w100fb_gpcntl_read(W100_GPIO_PORT_A);
122 ati_gpios[2] = w100fb_gpio_read(W100_GPIO_PORT_B);
123 ati_gpios[3] = w100fb_gpcntl_read(W100_GPIO_PORT_B);
124 w100fb_gpio_write(W100_GPIO_PORT_A, 0xDFE00000 );
125 w100fb_gpcntl_write(W100_GPIO_PORT_A, 0xFFFF0000 );
126 w100fb_gpio_write(W100_GPIO_PORT_B, 0x00000000 );
127 w100fb_gpcntl_write(W100_GPIO_PORT_B, 0xFFFFFFFF );
128 lcd_hw_off();
131 static void
132 hx4700_lcd_resume( struct w100fb_par *wfb )
134 w100fb_gpio_write(W100_GPIO_PORT_A, ati_gpios[0] );
135 w100fb_gpcntl_write(W100_GPIO_PORT_A, ati_gpios[1] );
136 w100fb_gpio_write(W100_GPIO_PORT_B, ati_gpios[2] );
137 w100fb_gpcntl_write(W100_GPIO_PORT_B, ati_gpios[3] );
138 lcd_hw_init();
141 #else
142 #define hx4700_lcd_resume NULL
143 #define hx4700_lcd_suspend NULL
144 #endif
146 struct w100_tg_info hx4700_tg_info = {
147 .suspend = hx4700_lcd_suspend,
148 .resume = hx4700_lcd_resume,
151 // W3220_VGA QVGA
152 static struct w100_gen_regs hx4700_w100_regs = {
153 .lcd_format = 0x00000003,
154 .lcdd_cntl1 = 0x00000000,
155 .lcdd_cntl2 = 0x0003ffff,
156 .genlcd_cntl1 = 0x00abf003, // 0x00fff003
157 .genlcd_cntl2 = 0x00000003,
158 .genlcd_cntl3 = 0x000102aa,
161 static struct w100_mode hx4700_w100_modes[] = {
163 .xres = 480,
164 .yres = 640,
165 .left_margin = 15,
166 .right_margin = 16,
167 .upper_margin = 8,
168 .lower_margin = 7,
169 .crtc_ss = 0x00000000,
170 .crtc_ls = 0xa1ff01f9, // 0x21ff01f9,
171 .crtc_gs = 0xc0000000, // 0x40000000,
172 .crtc_vpos_gs = 0x0000028f,
173 .crtc_ps1_active = 0x00000000, // 0x41060010
174 .crtc_rev = 0,
175 .crtc_dclk = 0x80000000,
176 .crtc_gclk = 0x040a0104,
177 .crtc_goe = 0,
178 .pll_freq = 95,
179 .pixclk_divider = 4,
180 .pixclk_divider_rotated = 4,
181 .pixclk_src = CLK_SRC_PLL,
182 .sysclk_divider = 0,
183 .sysclk_src = CLK_SRC_PLL,
186 .xres = 240,
187 .yres = 320,
188 .left_margin = 9,
189 .right_margin = 8,
190 .upper_margin = 5,
191 .lower_margin = 4,
192 .crtc_ss = 0x80150014,
193 .crtc_ls = 0xa0fb00f7,
194 .crtc_gs = 0xc0080007,
195 .crtc_vpos_gs = 0x00080007,
196 .crtc_rev = 0x0000000a,
197 .crtc_dclk = 0x81700030,
198 .crtc_gclk = 0x8015010f,
199 .crtc_goe = 0x00000000,
200 .pll_freq = 95,
201 .pixclk_divider = 4,
202 .pixclk_divider_rotated = 4,
203 .pixclk_src = CLK_SRC_PLL,
204 .sysclk_divider = 0,
205 .sysclk_src = CLK_SRC_PLL,
209 struct w100_mem_info hx4700_mem_info = {
210 .ext_cntl = 0x09640011,
211 .sdram_mode_reg = 0x00600021,
212 .ext_timing_cntl = 0x1a001545, // 0x15001545,
213 .io_cntl = 0x7ddd7333,
214 .size = 0x1fffff,
217 struct w100_bm_mem_info hx4700_bm_mem_info = {
218 .ext_mem_bw = 0x50413e01,
219 .offset = 0,
220 .ext_timing_ctl = 0x00043f7f,
221 .ext_cntl = 0x00000010,
222 .mode_reg = 0x00250000,
223 .io_cntl = 0x0fff0000,
224 .config = 0x08301480,
227 static struct w100_gpio_regs hx4700_w100_gpio_info = {
228 .init_data1 = 0xdfe00100, // GPIO_DATA
229 .gpio_dir1 = 0xffff0000, // GPIO_CNTL1
230 .gpio_oe1 = 0x00000000, // GPIO_CNTL2
231 .init_data2 = 0x00000000, // GPIO_DATA2
232 .gpio_dir2 = 0x00000000, // GPIO_CNTL3
233 .gpio_oe2 = 0x00000000, // GPIO_CNTL4
236 static struct w100fb_mach_info hx4700_fb_info = {
237 .tg = &hx4700_tg_info,
238 .mem = &hx4700_mem_info,
239 .bm_mem = &hx4700_bm_mem_info,
240 .gpio = &hx4700_w100_gpio_info,
241 .regs = &hx4700_w100_regs,
242 .modelist = hx4700_w100_modes,
243 .num_modes = 2,
244 .xtal_freq = 16000000,
248 static struct resource hx4700_fb_resources[] = {
249 [0] = {
250 .start = HX4700_ATI_W3220_PHYS,
251 .end = HX4700_ATI_W3220_PHYS + 0x00ffffff,
252 .flags = IORESOURCE_MEM,
256 static struct platform_device hx4700_fb_device = {
257 .name = "w100fb",
258 .id = -1,
259 .dev = {
260 .platform_data = &hx4700_fb_info,
262 .num_resources = ARRAY_SIZE( hx4700_fb_resources ),
263 .resource = hx4700_fb_resources,
266 static int
267 hx4700_lcd_probe( struct platform_device *dev )
269 lcd_hw_init();
270 return 0;
273 static int
274 hx4700_lcd_remove( struct platform_device *dev )
276 return 0;
279 static struct platform_driver hx4700_lcd_driver = {
280 .driver = {
281 .name = "hx4700-lcd",
283 .probe = hx4700_lcd_probe,
284 .remove = hx4700_lcd_remove,
288 static int __init
289 hx4700_lcd_init( void )
291 int ret;
293 printk( KERN_INFO "hx4700 LCD Driver\n" );
294 if (!machine_is_h4700())
295 return -ENODEV;
296 ret = platform_device_register( &hx4700_fb_device );
297 if (ret != 0)
298 return ret;
300 atifb_lcd_dev = lcd_device_register( "w100fb", (void *)&hx4700_fb_info,
301 &w3220_fb0_lcd );
302 if (IS_ERR( atifb_lcd_dev ))
303 return PTR_ERR( atifb_lcd_dev );
305 return platform_driver_register( &hx4700_lcd_driver );
309 static void __exit
310 hx4700_lcd_exit( void )
312 lcd_device_unregister( atifb_lcd_dev );
313 platform_device_unregister( &hx4700_fb_device );
314 platform_driver_unregister( &hx4700_lcd_driver );
317 module_init( hx4700_lcd_init );
318 module_exit( hx4700_lcd_exit );
320 MODULE_AUTHOR( "Todd Blumer, SDG Systems, LLC" );
321 MODULE_DESCRIPTION( "Framebuffer driver for iPAQ hx4700" );
322 MODULE_LICENSE( "GPL" );
324 /* vim600: set noexpandtab sw=8 ts=8 :*/