Merge branch 'linus' into x86/pat2
[linux-2.6] / arch / arm / mach-pxa / e800_lcd.c
1 /* e800_lcd.c
2  *
3  * This file contains the definitions for the LCD timings and functions
4  * to control the LCD power / frontlighting via the w100fb driver.
5  *
6  * (c) 2005 Ian Molton <spyro@f2s.com>
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License version 2 as
10  * published by the Free Software Foundation.
11  *
12  */
13
14 #include <linux/module.h>
15 #include <linux/device.h>
16 #include <linux/fb.h>
17 #include <linux/err.h>
18 #include <linux/platform_device.h>
19
20 #include <asm/mach-types.h>
21
22 #include <video/w100fb.h>
23
24 static struct w100_gen_regs e800_lcd_regs = {
25         .lcd_format =            0x00008003,
26         .lcdd_cntl1 =            0x02a00000,
27         .lcdd_cntl2 =            0x0003ffff,
28         .genlcd_cntl1 =          0x000ff2a3,
29         .genlcd_cntl2 =          0x000002a3,
30         .genlcd_cntl3 =          0x000102aa,
31 };
32
33 static struct w100_mode e800_lcd_mode[2] = {
34         [0] = {
35                 .xres            = 480,
36                 .yres            = 640,
37                 .left_margin     = 52,
38                 .right_margin    = 148,
39                 .upper_margin    = 2,
40                 .lower_margin    = 6,
41                 .crtc_ss         = 0x80350034,
42                 .crtc_ls         = 0x802b0026,
43                 .crtc_gs         = 0x80160016,
44                 .crtc_vpos_gs    = 0x00020003,
45                 .crtc_rev        = 0x0040001d,
46                 .crtc_dclk       = 0xe0000000,
47                 .crtc_gclk       = 0x82a50049,
48                 .crtc_goe        = 0x80ee001c,
49                 .crtc_ps1_active = 0x00000000,
50                 .pll_freq        = 128,
51                 .pixclk_divider         = 4,
52                 .pixclk_divider_rotated = 6,
53                 .pixclk_src     = CLK_SRC_PLL,
54                 .sysclk_divider  = 0,
55                 .sysclk_src     = CLK_SRC_PLL,
56         },
57         [1] = {
58                 .xres            = 240,
59                 .yres            = 320,
60                 .left_margin     = 15,
61                 .right_margin    = 88,
62                 .upper_margin    = 0,
63                 .lower_margin    = 7,
64                 .crtc_ss         = 0xd010000f,
65                 .crtc_ls         = 0x80070003,
66                 .crtc_gs         = 0x80000000,
67                 .crtc_vpos_gs    = 0x01460147,
68                 .crtc_rev        = 0x00400003,
69                 .crtc_dclk       = 0xa1700030,
70                 .crtc_gclk       = 0x814b0008,
71                 .crtc_goe        = 0x80cc0015,
72                 .crtc_ps1_active = 0x00000000,
73                 .pll_freq        = 100,
74                 .pixclk_divider         = 6, /* Wince uses 14 which gives a 7MHz pclk. */
75                 .pixclk_divider_rotated = 6, /* we want a 14MHz one (much nicer to look at) */
76                 .pixclk_src     = CLK_SRC_PLL,
77                 .sysclk_divider  = 0,
78                 .sysclk_src     = CLK_SRC_PLL,
79         }
80 };
81
82
83 static struct w100_gpio_regs e800_w100_gpio_info = {
84         .init_data1 = 0xc13fc019,
85         .gpio_dir1  = 0x3e40df7f,
86         .gpio_oe1   = 0x003c3000,
87         .init_data2 = 0x00000000,
88         .gpio_dir2  = 0x00000000,
89         .gpio_oe2   = 0x00000000,
90 };
91
92 static struct w100_mem_info e800_w100_mem_info = {
93         .ext_cntl        = 0x09640011,
94         .sdram_mode_reg  = 0x00600021,
95         .ext_timing_cntl = 0x10001545,
96         .io_cntl         = 0x7ddd7333,
97         .size            = 0x1fffff,
98 };
99
100 static void e800_tg_change(struct w100fb_par *par)
101 {
102         unsigned long tmp;
103
104         tmp = w100fb_gpio_read(W100_GPIO_PORT_A);
105         if (par->mode->xres == 480)
106                 tmp |= 0x100;
107         else
108                 tmp &= ~0x100;
109         w100fb_gpio_write(W100_GPIO_PORT_A, tmp);
110 }
111
112 static struct w100_tg_info e800_tg_info = {
113         .change = e800_tg_change,
114 };
115
116 static struct w100fb_mach_info e800_fb_info = {
117         .modelist   = e800_lcd_mode,
118         .num_modes  = 2,
119         .regs       = &e800_lcd_regs,
120         .gpio       = &e800_w100_gpio_info,
121         .mem        = &e800_w100_mem_info,
122         .tg         = &e800_tg_info,
123         .xtal_freq  = 16000000,
124 };
125
126 static struct resource e800_fb_resources[] = {
127         [0] = {
128                 .start          = 0x0c000000,
129                 .end            = 0x0cffffff,
130                 .flags          = IORESOURCE_MEM,
131         },
132 };
133
134 /* ----------------------- device declarations -------------------------- */
135
136
137 static struct platform_device e800_fb_device = {
138         .name           = "w100fb",
139         .id             = -1,
140         .dev            = {
141                 .platform_data  = &e800_fb_info,
142         },
143         .num_resources  = ARRAY_SIZE(e800_fb_resources),
144         .resource       = e800_fb_resources,
145 };
146
147 static int e800_lcd_init(void)
148 {
149         if (!machine_is_e800())
150                 return -ENODEV;
151
152         return platform_device_register(&e800_fb_device);
153 }
154
155 module_init(e800_lcd_init);
156
157 MODULE_AUTHOR("Ian Molton <spyro@f2s.com>");
158 MODULE_DESCRIPTION("e800 lcd driver");
159 MODULE_LICENSE("GPLv2");