aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/arm/mach-sa1100/assabet.c130
-rw-r--r--arch/arm/mach-sa1100/collie.c17
-rw-r--r--arch/arm/mach-sa1100/generic.c14
-rw-r--r--arch/arm/mach-sa1100/generic.h6
-rw-r--r--arch/arm/mach-sa1100/h3100.c23
-rw-r--r--arch/arm/mach-sa1100/h3600.c32
-rw-r--r--arch/arm/mach-sa1100/include/mach/SA-1100.h10
-rw-r--r--arch/arm/mach-sa1100/include/mach/shannon.h2
-rw-r--r--arch/arm/mach-sa1100/lart.c79
-rw-r--r--arch/arm/mach-sa1100/shannon.c17
-rw-r--r--drivers/video/sa1100fb.c493
-rw-r--r--drivers/video/sa1100fb.h76
-rw-r--r--include/video/sa1100fb.h63
13 files changed, 492 insertions, 470 deletions
diff --git a/arch/arm/mach-sa1100/assabet.c b/arch/arm/mach-sa1100/assabet.c
index e2d411a8d4ce..c3f5064df4bf 100644
--- a/arch/arm/mach-sa1100/assabet.c
+++ b/arch/arm/mach-sa1100/assabet.c
@@ -20,6 +20,8 @@
20#include <linux/delay.h> 20#include <linux/delay.h>
21#include <linux/mm.h> 21#include <linux/mm.h>
22 22
23#include <video/sa1100fb.h>
24
23#include <mach/hardware.h> 25#include <mach/hardware.h>
24#include <asm/mach-types.h> 26#include <asm/mach-types.h>
25#include <asm/irq.h> 27#include <asm/irq.h>
@@ -69,33 +71,6 @@ void ASSABET_BCR_frob(unsigned int mask, unsigned int val)
69 71
70EXPORT_SYMBOL(ASSABET_BCR_frob); 72EXPORT_SYMBOL(ASSABET_BCR_frob);
71 73
72static void assabet_backlight_power(int on)
73{
74#ifndef ASSABET_PAL_VIDEO
75 if (on)
76 ASSABET_BCR_set(ASSABET_BCR_LIGHT_ON);
77 else
78#endif
79 ASSABET_BCR_clear(ASSABET_BCR_LIGHT_ON);
80}
81
82/*
83 * Turn on/off the backlight. When turning the backlight on,
84 * we wait 500us after turning it on so we don't cause the
85 * supplies to droop when we enable the LCD controller (and
86 * cause a hard reset.)
87 */
88static void assabet_lcd_power(int on)
89{
90#ifndef ASSABET_PAL_VIDEO
91 if (on) {
92 ASSABET_BCR_set(ASSABET_BCR_LCD_ON);
93 udelay(500);
94 } else
95#endif
96 ASSABET_BCR_clear(ASSABET_BCR_LCD_ON);
97}
98
99 74
100/* 75/*
101 * Assabet flash support code. 76 * Assabet flash support code.
@@ -197,6 +172,99 @@ static struct mcp_plat_data assabet_mcp_data = {
197 .sclk_rate = 11981000, 172 .sclk_rate = 11981000,
198}; 173};
199 174
175static void assabet_lcd_set_visual(u32 visual)
176{
177 u_int is_true_color = visual == FB_VISUAL_TRUECOLOR;
178
179 if (machine_is_assabet()) {
180#if 1 // phase 4 or newer Assabet's
181 if (is_true_color)
182 ASSABET_BCR_set(ASSABET_BCR_LCD_12RGB);
183 else
184 ASSABET_BCR_clear(ASSABET_BCR_LCD_12RGB);
185#else
186 // older Assabet's
187 if (is_true_color)
188 ASSABET_BCR_clear(ASSABET_BCR_LCD_12RGB);
189 else
190 ASSABET_BCR_set(ASSABET_BCR_LCD_12RGB);
191#endif
192 }
193}
194
195#ifndef ASSABET_PAL_VIDEO
196static void assabet_lcd_backlight_power(int on)
197{
198 if (on)
199 ASSABET_BCR_set(ASSABET_BCR_LIGHT_ON);
200 else
201 ASSABET_BCR_clear(ASSABET_BCR_LIGHT_ON);
202}
203
204/*
205 * Turn on/off the backlight. When turning the backlight on, we wait
206 * 500us after turning it on so we don't cause the supplies to droop
207 * when we enable the LCD controller (and cause a hard reset.)
208 */
209static void assabet_lcd_power(int on)
210{
211 if (on) {
212 ASSABET_BCR_set(ASSABET_BCR_LCD_ON);
213 udelay(500);
214 } else
215 ASSABET_BCR_clear(ASSABET_BCR_LCD_ON);
216}
217
218/*
219 * The assabet uses a sharp LQ039Q2DS54 LCD module. It is actually
220 * takes an RGB666 signal, but we provide it with an RGB565 signal
221 * instead (def_rgb_16).
222 */
223static struct sa1100fb_mach_info lq039q2ds54_info = {
224 .pixclock = 171521, .bpp = 16,
225 .xres = 320, .yres = 240,
226
227 .hsync_len = 5, .vsync_len = 1,
228 .left_margin = 61, .upper_margin = 3,
229 .right_margin = 9, .lower_margin = 0,
230
231 .sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
232
233 .lccr0 = LCCR0_Color | LCCR0_Sngl | LCCR0_Act,
234 .lccr3 = LCCR3_OutEnH | LCCR3_PixRsEdg | LCCR3_ACBsDiv(2),
235
236 .backlight_power = assabet_lcd_backlight_power,
237 .lcd_power = assabet_lcd_power,
238 .set_visual = assabet_lcd_set_visual,
239};
240#else
241static void assabet_pal_backlight_power(int on)
242{
243 ASSABET_BCR_clear(ASSABET_BCR_LIGHT_ON);
244}
245
246static void assabet_pal_power(int on)
247{
248 ASSABET_BCR_clear(ASSABET_BCR_LCD_ON);
249}
250
251static struct sa1100fb_mach_info pal_info = {
252 .pixclock = 67797, .bpp = 16,
253 .xres = 640, .yres = 512,
254
255 .hsync_len = 64, .vsync_len = 6,
256 .left_margin = 125, .upper_margin = 70,
257 .right_margin = 115, .lower_margin = 36,
258
259 .lccr0 = LCCR0_Color | LCCR0_Sngl | LCCR0_Act,
260 .lccr3 = LCCR3_OutEnH | LCCR3_PixRsEdg | LCCR3_ACBsDiv(512),
261
262 .backlight_power = assabet_pal_backlight_power,
263 .lcd_power = assabet_pal_power,
264 .set_visual = assabet_lcd_set_visual,
265};
266#endif
267
200#ifdef CONFIG_ASSABET_NEPONSET 268#ifdef CONFIG_ASSABET_NEPONSET
201static struct resource neponset_resources[] = { 269static struct resource neponset_resources[] = {
202 DEFINE_RES_MEM(0x10000000, 0x08000000), 270 DEFINE_RES_MEM(0x10000000, 0x08000000),
@@ -241,9 +309,6 @@ static void __init assabet_init(void)
241 PPDR |= PPC_TXD3 | PPC_TXD1; 309 PPDR |= PPC_TXD3 | PPC_TXD1;
242 PPSR |= PPC_TXD3 | PPC_TXD1; 310 PPSR |= PPC_TXD3 | PPC_TXD1;
243 311
244 sa1100fb_lcd_power = assabet_lcd_power;
245 sa1100fb_backlight_power = assabet_backlight_power;
246
247 if (machine_has_neponset()) { 312 if (machine_has_neponset()) {
248 /* 313 /*
249 * Angel sets this, but other bootloaders may not. 314 * Angel sets this, but other bootloaders may not.
@@ -262,6 +327,11 @@ static void __init assabet_init(void)
262#endif 327#endif
263 } 328 }
264 329
330#ifndef ASSABET_PAL_VIDEO
331 sa11x0_register_lcd(&lq039q2ds54_info);
332#else
333 sa11x0_register_lcd(&pal_video);
334#endif
265 sa11x0_register_mtd(&assabet_flash_data, assabet_flash_resources, 335 sa11x0_register_mtd(&assabet_flash_data, assabet_flash_resources,
266 ARRAY_SIZE(assabet_flash_resources)); 336 ARRAY_SIZE(assabet_flash_resources));
267 sa11x0_register_irda(&assabet_irda_data); 337 sa11x0_register_irda(&assabet_irda_data);
diff --git a/arch/arm/mach-sa1100/collie.c b/arch/arm/mach-sa1100/collie.c
index dbe5cf719f7e..841041e11815 100644
--- a/arch/arm/mach-sa1100/collie.c
+++ b/arch/arm/mach-sa1100/collie.c
@@ -28,6 +28,8 @@
28#include <linux/gpio.h> 28#include <linux/gpio.h>
29#include <linux/pda_power.h> 29#include <linux/pda_power.h>
30 30
31#include <video/sa1100fb.h>
32
31#include <mach/hardware.h> 33#include <mach/hardware.h>
32#include <asm/mach-types.h> 34#include <asm/mach-types.h>
33#include <asm/irq.h> 35#include <asm/irq.h>
@@ -294,6 +296,20 @@ static struct resource collie_flash_resources[] = {
294 DEFINE_RES_MEM(SA1100_CS0_PHYS, SZ_32M), 296 DEFINE_RES_MEM(SA1100_CS0_PHYS, SZ_32M),
295}; 297};
296 298
299static struct sa1100fb_mach_info collie_lcd_info = {
300 .pixclock = 171521, .bpp = 16,
301 .xres = 320, .yres = 240,
302
303 .hsync_len = 5, .vsync_len = 1,
304 .left_margin = 11, .upper_margin = 2,
305 .right_margin = 30, .lower_margin = 0,
306
307 .sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
308
309 .lccr0 = LCCR0_Color | LCCR0_Sngl | LCCR0_Act,
310 .lccr3 = LCCR3_OutEnH | LCCR3_PixRsEdg | LCCR3_ACBsDiv(2),
311};
312
297static void __init collie_init(void) 313static void __init collie_init(void)
298{ 314{
299 int ret = 0; 315 int ret = 0;
@@ -332,6 +348,7 @@ static void __init collie_init(void)
332 printk(KERN_WARNING "collie: Unable to register LoCoMo device\n"); 348 printk(KERN_WARNING "collie: Unable to register LoCoMo device\n");
333 } 349 }
334 350
351 sa11x0_register_lcd(&collie_lcd_info);
335 sa11x0_register_mtd(&collie_flash_data, collie_flash_resources, 352 sa11x0_register_mtd(&collie_flash_data, collie_flash_resources,
336 ARRAY_SIZE(collie_flash_resources)); 353 ARRAY_SIZE(collie_flash_resources));
337 sa11x0_register_mcp(&collie_mcp_data); 354 sa11x0_register_mcp(&collie_mcp_data);
diff --git a/arch/arm/mach-sa1100/generic.c b/arch/arm/mach-sa1100/generic.c
index 01a20ea35b53..0296d69622ac 100644
--- a/arch/arm/mach-sa1100/generic.c
+++ b/arch/arm/mach-sa1100/generic.c
@@ -20,6 +20,8 @@
20#include <linux/ioport.h> 20#include <linux/ioport.h>
21#include <linux/platform_device.h> 21#include <linux/platform_device.h>
22 22
23#include <video/sa1100fb.h>
24
23#include <asm/div64.h> 25#include <asm/div64.h>
24#include <mach/hardware.h> 26#include <mach/hardware.h>
25#include <asm/system.h> 27#include <asm/system.h>
@@ -247,6 +249,11 @@ static struct platform_device sa11x0fb_device = {
247 .resource = sa11x0fb_resources, 249 .resource = sa11x0fb_resources,
248}; 250};
249 251
252void sa11x0_register_lcd(struct sa1100fb_mach_info *inf)
253{
254 sa11x0_register_device(&sa11x0fb_device, inf);
255}
256
250static struct platform_device sa11x0pcmcia_device = { 257static struct platform_device sa11x0pcmcia_device = {
251 .name = "sa11x0-pcmcia", 258 .name = "sa11x0-pcmcia",
252 .id = -1, 259 .id = -1,
@@ -319,7 +326,6 @@ static struct platform_device *sa11x0_devices[] __initdata = {
319 &sa11x0uart3_device, 326 &sa11x0uart3_device,
320 &sa11x0ssp_device, 327 &sa11x0ssp_device,
321 &sa11x0pcmcia_device, 328 &sa11x0pcmcia_device,
322 &sa11x0fb_device,
323 &sa11x0rtc_device, 329 &sa11x0rtc_device,
324 &sa11x0dma_device, 330 &sa11x0dma_device,
325}; 331};
@@ -332,12 +338,6 @@ static int __init sa1100_init(void)
332 338
333arch_initcall(sa1100_init); 339arch_initcall(sa1100_init);
334 340
335void (*sa1100fb_backlight_power)(int on);
336void (*sa1100fb_lcd_power)(int on);
337
338EXPORT_SYMBOL(sa1100fb_backlight_power);
339EXPORT_SYMBOL(sa1100fb_lcd_power);
340
341 341
342/* 342/*
343 * Common I/O mapping: 343 * Common I/O mapping:
diff --git a/arch/arm/mach-sa1100/generic.h b/arch/arm/mach-sa1100/generic.h
index 33268cf6be36..5c68be858e0c 100644
--- a/arch/arm/mach-sa1100/generic.h
+++ b/arch/arm/mach-sa1100/generic.h
@@ -16,9 +16,6 @@ extern void sa11x0_restart(char, const char *);
16 mi->bank[__nr].start = (__start), \ 16 mi->bank[__nr].start = (__start), \
17 mi->bank[__nr].size = (__size) 17 mi->bank[__nr].size = (__size)
18 18
19extern void (*sa1100fb_backlight_power)(int on);
20extern void (*sa1100fb_lcd_power)(int on);
21
22extern void sa1110_mb_enable(void); 19extern void sa1110_mb_enable(void);
23extern void sa1110_mb_disable(void); 20extern void sa1110_mb_disable(void);
24 21
@@ -40,3 +37,6 @@ void sa11x0_register_irda(struct irda_platform_data *irda);
40 37
41struct mcp_plat_data; 38struct mcp_plat_data;
42void sa11x0_register_mcp(struct mcp_plat_data *data); 39void sa11x0_register_mcp(struct mcp_plat_data *data);
40
41struct sa1100fb_mach_info;
42void sa11x0_register_lcd(struct sa1100fb_mach_info *inf);
diff --git a/arch/arm/mach-sa1100/h3100.c b/arch/arm/mach-sa1100/h3100.c
index 1e6b3c105ba6..f23e7d0b2fba 100644
--- a/arch/arm/mach-sa1100/h3100.c
+++ b/arch/arm/mach-sa1100/h3100.c
@@ -14,6 +14,8 @@
14#include <linux/kernel.h> 14#include <linux/kernel.h>
15#include <linux/gpio.h> 15#include <linux/gpio.h>
16 16
17#include <video/sa1100fb.h>
18
17#include <asm/mach-types.h> 19#include <asm/mach-types.h>
18#include <asm/mach/arch.h> 20#include <asm/mach/arch.h>
19#include <asm/mach/irda.h> 21#include <asm/mach/irda.h>
@@ -36,13 +38,28 @@ static void h3100_lcd_power(int enable)
36 } 38 }
37} 39}
38 40
41static struct sa1100fb_mach_info h3100_lcd_info = {
42 .pixclock = 406977, .bpp = 4,
43 .xres = 320, .yres = 240,
44
45 .hsync_len = 26, .vsync_len = 41,
46 .left_margin = 4, .upper_margin = 0,
47 .right_margin = 4, .lower_margin = 0,
48
49 .sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
50 .cmap_greyscale = 1,
51 .cmap_inverse = 1,
52
53 .lccr0 = LCCR0_Mono | LCCR0_4PixMono | LCCR0_Sngl | LCCR0_Pas,
54 .lccr3 = LCCR3_OutEnH | LCCR3_PixRsEdg | LCCR3_ACBsDiv(2),
55
56 .lcd_power = h3100_lcd_power,
57};
39 58
40static void __init h3100_map_io(void) 59static void __init h3100_map_io(void)
41{ 60{
42 h3xxx_map_io(); 61 h3xxx_map_io();
43 62
44 sa1100fb_lcd_power = h3100_lcd_power;
45
46 /* Older bootldrs put GPIO2-9 in alternate mode on the 63 /* Older bootldrs put GPIO2-9 in alternate mode on the
47 assumption that they are used for video */ 64 assumption that they are used for video */
48 GAFR &= ~0x000001fb; 65 GAFR &= ~0x000001fb;
@@ -80,6 +97,8 @@ static void __init h3100_mach_init(void)
80{ 97{
81 h3xxx_init_gpio(h3100_default_gpio, ARRAY_SIZE(h3100_default_gpio)); 98 h3xxx_init_gpio(h3100_default_gpio, ARRAY_SIZE(h3100_default_gpio));
82 h3xxx_mach_init(); 99 h3xxx_mach_init();
100
101 sa11x0_register_lcd(&h3100_lcd_info);
83 sa11x0_register_irda(&h3100_irda_data); 102 sa11x0_register_irda(&h3100_irda_data);
84} 103}
85 104
diff --git a/arch/arm/mach-sa1100/h3600.c b/arch/arm/mach-sa1100/h3600.c
index 6b58e7460ecf..2feac56ec90d 100644
--- a/arch/arm/mach-sa1100/h3600.c
+++ b/arch/arm/mach-sa1100/h3600.c
@@ -14,6 +14,8 @@
14#include <linux/kernel.h> 14#include <linux/kernel.h>
15#include <linux/gpio.h> 15#include <linux/gpio.h>
16 16
17#include <video/sa1100fb.h>
18
17#include <asm/mach-types.h> 19#include <asm/mach-types.h>
18#include <asm/mach/arch.h> 20#include <asm/mach/arch.h>
19#include <asm/mach/irda.h> 21#include <asm/mach/irda.h>
@@ -56,11 +58,35 @@ err2: gpio_free(H3XXX_EGPIO_LCD_ON);
56err1: return; 58err1: return;
57} 59}
58 60
61static const struct sa1100fb_rgb h3600_rgb_16 = {
62 .red = { .offset = 12, .length = 4, },
63 .green = { .offset = 7, .length = 4, },
64 .blue = { .offset = 1, .length = 4, },
65 .transp = { .offset = 0, .length = 0, },
66};
67
68static struct sa1100fb_mach_info h3600_lcd_info = {
69 .pixclock = 174757, .bpp = 16,
70 .xres = 320, .yres = 240,
71
72 .hsync_len = 3, .vsync_len = 3,
73 .left_margin = 12, .upper_margin = 10,
74 .right_margin = 17, .lower_margin = 1,
75
76 .cmap_static = 1,
77
78 .lccr0 = LCCR0_Color | LCCR0_Sngl | LCCR0_Act,
79 .lccr3 = LCCR3_OutEnH | LCCR3_PixRsEdg | LCCR3_ACBsDiv(2),
80
81 .rgb[RGB_16] = &h3600_rgb_16,
82
83 .lcd_power = h3600_lcd_power,
84};
85
86
59static void __init h3600_map_io(void) 87static void __init h3600_map_io(void)
60{ 88{
61 h3xxx_map_io(); 89 h3xxx_map_io();
62
63 sa1100fb_lcd_power = h3600_lcd_power;
64} 90}
65 91
66/* 92/*
@@ -121,6 +147,8 @@ static void __init h3600_mach_init(void)
121{ 147{
122 h3xxx_init_gpio(h3600_default_gpio, ARRAY_SIZE(h3600_default_gpio)); 148 h3xxx_init_gpio(h3600_default_gpio, ARRAY_SIZE(h3600_default_gpio));
123 h3xxx_mach_init(); 149 h3xxx_mach_init();
150
151 sa11x0_register_lcd(&h3600_lcd_info);
124 sa11x0_register_irda(&h3600_irda_data); 152 sa11x0_register_irda(&h3600_irda_data);
125} 153}
126 154
diff --git a/arch/arm/mach-sa1100/include/mach/SA-1100.h b/arch/arm/mach-sa1100/include/mach/SA-1100.h
index 335a1ff21faf..3f2d1b60188c 100644
--- a/arch/arm/mach-sa1100/include/mach/SA-1100.h
+++ b/arch/arm/mach-sa1100/include/mach/SA-1100.h
@@ -1688,16 +1688,6 @@
1688#define LCD_Int100_0A 0xF /* LCD Intensity = 100.0% = 1 */ 1688#define LCD_Int100_0A 0xF /* LCD Intensity = 100.0% = 1 */
1689 /* (Alternative) */ 1689 /* (Alternative) */
1690 1690
1691#define LCCR0 __REG(0xB0100000) /* LCD Control Reg. 0 */
1692#define LCSR __REG(0xB0100004) /* LCD Status Reg. */
1693#define DBAR1 __REG(0xB0100010) /* LCD DMA Base Address Reg. channel 1 */
1694#define DCAR1 __REG(0xB0100014) /* LCD DMA Current Address Reg. channel 1 */
1695#define DBAR2 __REG(0xB0100018) /* LCD DMA Base Address Reg. channel 2 */
1696#define DCAR2 __REG(0xB010001C) /* LCD DMA Current Address Reg. channel 2 */
1697#define LCCR1 __REG(0xB0100020) /* LCD Control Reg. 1 */
1698#define LCCR2 __REG(0xB0100024) /* LCD Control Reg. 2 */
1699#define LCCR3 __REG(0xB0100028) /* LCD Control Reg. 3 */
1700
1701#define LCCR0_LEN 0x00000001 /* LCD ENable */ 1691#define LCCR0_LEN 0x00000001 /* LCD ENable */
1702#define LCCR0_CMS 0x00000002 /* Color/Monochrome display Select */ 1692#define LCCR0_CMS 0x00000002 /* Color/Monochrome display Select */
1703#define LCCR0_Color (LCCR0_CMS*0) /* Color display */ 1693#define LCCR0_Color (LCCR0_CMS*0) /* Color display */
diff --git a/arch/arm/mach-sa1100/include/mach/shannon.h b/arch/arm/mach-sa1100/include/mach/shannon.h
index ec27d6e12140..a0d1114c45ed 100644
--- a/arch/arm/mach-sa1100/include/mach/shannon.h
+++ b/arch/arm/mach-sa1100/include/mach/shannon.h
@@ -21,7 +21,7 @@
21#define SHANNON_GPIO_U3_RTS GPIO_GPIO (19) /* ?? */ 21#define SHANNON_GPIO_U3_RTS GPIO_GPIO (19) /* ?? */
22#define SHANNON_GPIO_U3_CTS GPIO_GPIO (20) /* ?? */ 22#define SHANNON_GPIO_U3_CTS GPIO_GPIO (20) /* ?? */
23#define SHANNON_GPIO_SENSE_12V GPIO_GPIO (21) /* Input, 12v flash unprotect detected */ 23#define SHANNON_GPIO_SENSE_12V GPIO_GPIO (21) /* Input, 12v flash unprotect detected */
24#define SHANNON_GPIO_DISP_EN GPIO_GPIO (22) /* out */ 24#define SHANNON_GPIO_DISP_EN 22 /* out */
25/* XXX GPIO 23 unaccounted for */ 25/* XXX GPIO 23 unaccounted for */
26#define SHANNON_GPIO_EJECT_0 GPIO_GPIO (24) /* in */ 26#define SHANNON_GPIO_EJECT_0 GPIO_GPIO (24) /* in */
27#define SHANNON_IRQ_GPIO_EJECT_0 IRQ_GPIO24 27#define SHANNON_IRQ_GPIO_EJECT_0 IRQ_GPIO24
diff --git a/arch/arm/mach-sa1100/lart.c b/arch/arm/mach-sa1100/lart.c
index af4e2761f3db..463a322a425b 100644
--- a/arch/arm/mach-sa1100/lart.c
+++ b/arch/arm/mach-sa1100/lart.c
@@ -6,6 +6,8 @@
6#include <linux/kernel.h> 6#include <linux/kernel.h>
7#include <linux/tty.h> 7#include <linux/tty.h>
8 8
9#include <video/sa1100fb.h>
10
9#include <mach/hardware.h> 11#include <mach/hardware.h>
10#include <asm/setup.h> 12#include <asm/setup.h>
11#include <asm/mach-types.h> 13#include <asm/mach-types.h>
@@ -26,8 +28,85 @@ static struct mcp_plat_data lart_mcp_data = {
26 .sclk_rate = 11981000, 28 .sclk_rate = 11981000,
27}; 29};
28 30
31#ifdef LART_GREY_LCD
32static struct sa1100fb_mach_info lart_grey_info = {
33 .pixclock = 150000, .bpp = 4,
34 .xres = 320, .yres = 240,
35
36 .hsync_len = 1, .vsync_len = 1,
37 .left_margin = 4, .upper_margin = 0,
38 .right_margin = 2, .lower_margin = 0,
39
40 .cmap_greyscale = 1,
41 .sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
42
43 .lccr0 = LCCR0_Mono | LCCR0_Sngl | LCCR0_Pas | LCCR0_4PixMono,
44 .lccr3 = LCCR3_OutEnH | LCCR3_PixRsEdg | LCCR3_ACBsDiv(512),
45};
46#endif
47#ifdef LART_COLOR_LCD
48static struct sa1100fb_mach_info lart_color_info = {
49 .pixclock = 150000, .bpp = 16,
50 .xres = 320, .yres = 240,
51
52 .hsync_len = 2, .vsync_len = 3,
53 .left_margin = 69, .upper_margin = 14,
54 .right_margin = 8, .lower_margin = 4,
55
56 .lccr0 = LCCR0_Color | LCCR0_Sngl | LCCR0_Act,
57 .lccr3 = LCCR3_OutEnH | LCCR3_PixFlEdg | LCCR3_ACBsDiv(512),
58};
59#endif
60#ifdef LART_VIDEO_OUT
61static struct sa1100fb_mach_info lart_video_info = {
62 .pixclock = 39721, .bpp = 16,
63 .xres = 640, .yres = 480,
64
65 .hsync_len = 95, .vsync_len = 2,
66 .left_margin = 40, .upper_margin = 32,
67 .right_margin = 24, .lower_margin = 11,
68
69 .sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
70
71 .lccr0 = LCCR0_Color | LCCR0_Sngl | LCCR0_Act,
72 .lccr3 = LCCR3_OutEnL | LCCR3_PixFlEdg | LCCR3_ACBsDiv(512),
73};
74#endif
75
76#ifdef LART_KIT01_LCD
77static struct sa1100fb_mach_info lart_kit01_info = {
78 .pixclock = 63291, .bpp = 16,
79 .xres = 640, .yres = 480,
80
81 .hsync_len = 64, .vsync_len = 3,
82 .left_margin = 122, .upper_margin = 45,
83 .right_margin = 10, .lower_margin = 10,
84
85 .lccr0 = LCCR0_Color | LCCR0_Sngl | LCCR0_Act,
86 .lccr3 = LCCR3_OutEnH | LCCR3_PixFlEdg
87};
88#endif
89
29static void __init lart_init(void) 90static void __init lart_init(void)
30{ 91{
92 struct sa1100fb_mach_info *inf = NULL;
93
94#ifdef LART_GREY_LCD
95 inf = &lart_grey_info;
96#endif
97#ifdef LART_COLOR_LCD
98 inf = &lart_color_info;
99#endif
100#ifdef LART_VIDEO_OUT
101 inf = &lart_video_info;
102#endif
103#ifdef LART_KIT01_LCD
104 inf = &lart_kit01_info;
105#endif
106
107 if (inf)
108 sa11x0_register_lcd(inf);
109
31 sa11x0_register_mcp(&lart_mcp_data); 110 sa11x0_register_mcp(&lart_mcp_data);
32} 111}
33 112
diff --git a/arch/arm/mach-sa1100/shannon.c b/arch/arm/mach-sa1100/shannon.c
index 5fd615649847..77b2b9b522ac 100644
--- a/arch/arm/mach-sa1100/shannon.c
+++ b/arch/arm/mach-sa1100/shannon.c
@@ -9,6 +9,8 @@
9#include <linux/mtd/mtd.h> 9#include <linux/mtd/mtd.h>
10#include <linux/mtd/partitions.h> 10#include <linux/mtd/partitions.h>
11 11
12#include <video/sa1100fb.h>
13
12#include <mach/hardware.h> 14#include <mach/hardware.h>
13#include <asm/mach-types.h> 15#include <asm/mach-types.h>
14#include <asm/setup.h> 16#include <asm/setup.h>
@@ -54,8 +56,23 @@ static struct mcp_plat_data shannon_mcp_data = {
54 .sclk_rate = 11981000, 56 .sclk_rate = 11981000,
55}; 57};
56 58
59static struct sa1100fb_mach_info shannon_lcd_info = {
60 .pixclock = 152500, .bpp = 8,
61 .xres = 640, .yres = 480,
62
63 .hsync_len = 4, .vsync_len = 3,
64 .left_margin = 2, .upper_margin = 0,
65 .right_margin = 1, .lower_margin = 0,
66
67 .sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
68
69 .lccr0 = LCCR0_Color | LCCR0_Dual | LCCR0_Pas,
70 .lccr3 = LCCR3_ACBsDiv(512),
71};
72
57static void __init shannon_init(void) 73static void __init shannon_init(void)
58{ 74{
75 sa11x0_register_lcd(&shannon_lcd_info);
59 sa11x0_register_mtd(&shannon_flash_data, &shannon_flash_resource, 1); 76 sa11x0_register_mtd(&shannon_flash_data, &shannon_flash_resource, 1);
60 sa11x0_register_mcp(&shannon_mcp_data); 77 sa11x0_register_mcp(&shannon_mcp_data);
61} 78}
diff --git a/drivers/video/sa1100fb.c b/drivers/video/sa1100fb.c
index 98d55d0e2da5..b6325848ad61 100644
--- a/drivers/video/sa1100fb.c
+++ b/drivers/video/sa1100fb.c
@@ -173,282 +173,48 @@
173#include <linux/init.h> 173#include <linux/init.h>
174#include <linux/ioport.h> 174#include <linux/ioport.h>
175#include <linux/cpufreq.h> 175#include <linux/cpufreq.h>
176#include <linux/gpio.h>
176#include <linux/platform_device.h> 177#include <linux/platform_device.h>
177#include <linux/dma-mapping.h> 178#include <linux/dma-mapping.h>
178#include <linux/mutex.h> 179#include <linux/mutex.h>
179#include <linux/io.h> 180#include <linux/io.h>
180 181
182#include <video/sa1100fb.h>
183
181#include <mach/hardware.h> 184#include <mach/hardware.h>
182#include <asm/mach-types.h> 185#include <asm/mach-types.h>
183#include <mach/assabet.h>
184#include <mach/shannon.h> 186#include <mach/shannon.h>
185 187
186/* 188/*
187 * debugging?
188 */
189#define DEBUG 0
190/*
191 * Complain if VAR is out of range. 189 * Complain if VAR is out of range.
192 */ 190 */
193#define DEBUG_VAR 1 191#define DEBUG_VAR 1
194 192
195#undef ASSABET_PAL_VIDEO
196
197#include "sa1100fb.h" 193#include "sa1100fb.h"
198 194
199extern void (*sa1100fb_backlight_power)(int on); 195static const struct sa1100fb_rgb rgb_4 = {
200extern void (*sa1100fb_lcd_power)(int on);
201
202static struct sa1100fb_rgb rgb_4 = {
203 .red = { .offset = 0, .length = 4, }, 196 .red = { .offset = 0, .length = 4, },
204 .green = { .offset = 0, .length = 4, }, 197 .green = { .offset = 0, .length = 4, },
205 .blue = { .offset = 0, .length = 4, }, 198 .blue = { .offset = 0, .length = 4, },
206 .transp = { .offset = 0, .length = 0, }, 199 .transp = { .offset = 0, .length = 0, },
207}; 200};
208 201
209static struct sa1100fb_rgb rgb_8 = { 202static const struct sa1100fb_rgb rgb_8 = {
210 .red = { .offset = 0, .length = 8, }, 203 .red = { .offset = 0, .length = 8, },
211 .green = { .offset = 0, .length = 8, }, 204 .green = { .offset = 0, .length = 8, },
212 .blue = { .offset = 0, .length = 8, }, 205 .blue = { .offset = 0, .length = 8, },
213 .transp = { .offset = 0, .length = 0, }, 206 .transp = { .offset = 0, .length = 0, },
214}; 207};
215 208
216static struct sa1100fb_rgb def_rgb_16 = { 209static const struct sa1100fb_rgb def_rgb_16 = {
217 .red = { .offset = 11, .length = 5, }, 210 .red = { .offset = 11, .length = 5, },
218 .green = { .offset = 5, .length = 6, }, 211 .green = { .offset = 5, .length = 6, },
219 .blue = { .offset = 0, .length = 5, }, 212 .blue = { .offset = 0, .length = 5, },
220 .transp = { .offset = 0, .length = 0, }, 213 .transp = { .offset = 0, .length = 0, },
221}; 214};
222 215
223#ifdef CONFIG_SA1100_ASSABET
224#ifndef ASSABET_PAL_VIDEO
225/*
226 * The assabet uses a sharp LQ039Q2DS54 LCD module. It is actually
227 * takes an RGB666 signal, but we provide it with an RGB565 signal
228 * instead (def_rgb_16).
229 */
230static struct sa1100fb_mach_info lq039q2ds54_info __initdata = {
231 .pixclock = 171521, .bpp = 16,
232 .xres = 320, .yres = 240,
233
234 .hsync_len = 5, .vsync_len = 1,
235 .left_margin = 61, .upper_margin = 3,
236 .right_margin = 9, .lower_margin = 0,
237
238 .sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
239
240 .lccr0 = LCCR0_Color | LCCR0_Sngl | LCCR0_Act,
241 .lccr3 = LCCR3_OutEnH | LCCR3_PixRsEdg | LCCR3_ACBsDiv(2),
242};
243#else
244static struct sa1100fb_mach_info pal_info __initdata = {
245 .pixclock = 67797, .bpp = 16,
246 .xres = 640, .yres = 512,
247
248 .hsync_len = 64, .vsync_len = 6,
249 .left_margin = 125, .upper_margin = 70,
250 .right_margin = 115, .lower_margin = 36,
251
252 .lccr0 = LCCR0_Color | LCCR0_Sngl | LCCR0_Act,
253 .lccr3 = LCCR3_OutEnH | LCCR3_PixRsEdg | LCCR3_ACBsDiv(512),
254};
255#endif
256#endif
257
258#ifdef CONFIG_SA1100_H3600
259static struct sa1100fb_mach_info h3600_info __initdata = {
260 .pixclock = 174757, .bpp = 16,
261 .xres = 320, .yres = 240,
262
263 .hsync_len = 3, .vsync_len = 3,
264 .left_margin = 12, .upper_margin = 10,
265 .right_margin = 17, .lower_margin = 1,
266
267 .cmap_static = 1,
268
269 .lccr0 = LCCR0_Color | LCCR0_Sngl | LCCR0_Act,
270 .lccr3 = LCCR3_OutEnH | LCCR3_PixRsEdg | LCCR3_ACBsDiv(2),
271};
272
273static struct sa1100fb_rgb h3600_rgb_16 = {
274 .red = { .offset = 12, .length = 4, },
275 .green = { .offset = 7, .length = 4, },
276 .blue = { .offset = 1, .length = 4, },
277 .transp = { .offset = 0, .length = 0, },
278};
279#endif
280
281#ifdef CONFIG_SA1100_H3100
282static struct sa1100fb_mach_info h3100_info __initdata = {
283 .pixclock = 406977, .bpp = 4,
284 .xres = 320, .yres = 240,
285
286 .hsync_len = 26, .vsync_len = 41,
287 .left_margin = 4, .upper_margin = 0,
288 .right_margin = 4, .lower_margin = 0,
289
290 .sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
291 .cmap_greyscale = 1,
292 .cmap_inverse = 1,
293
294 .lccr0 = LCCR0_Mono | LCCR0_4PixMono | LCCR0_Sngl | LCCR0_Pas,
295 .lccr3 = LCCR3_OutEnH | LCCR3_PixRsEdg | LCCR3_ACBsDiv(2),
296};
297#endif
298
299#ifdef CONFIG_SA1100_COLLIE
300static struct sa1100fb_mach_info collie_info __initdata = {
301 .pixclock = 171521, .bpp = 16,
302 .xres = 320, .yres = 240,
303
304 .hsync_len = 5, .vsync_len = 1,
305 .left_margin = 11, .upper_margin = 2,
306 .right_margin = 30, .lower_margin = 0,
307
308 .sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
309
310 .lccr0 = LCCR0_Color | LCCR0_Sngl | LCCR0_Act,
311 .lccr3 = LCCR3_OutEnH | LCCR3_PixRsEdg | LCCR3_ACBsDiv(2),
312};
313#endif
314
315#ifdef LART_GREY_LCD
316static struct sa1100fb_mach_info lart_grey_info __initdata = {
317 .pixclock = 150000, .bpp = 4,
318 .xres = 320, .yres = 240,
319
320 .hsync_len = 1, .vsync_len = 1,
321 .left_margin = 4, .upper_margin = 0,
322 .right_margin = 2, .lower_margin = 0,
323
324 .cmap_greyscale = 1,
325 .sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
326
327 .lccr0 = LCCR0_Mono | LCCR0_Sngl | LCCR0_Pas | LCCR0_4PixMono,
328 .lccr3 = LCCR3_OutEnH | LCCR3_PixRsEdg | LCCR3_ACBsDiv(512),
329};
330#endif
331#ifdef LART_COLOR_LCD
332static struct sa1100fb_mach_info lart_color_info __initdata = {
333 .pixclock = 150000, .bpp = 16,
334 .xres = 320, .yres = 240,
335
336 .hsync_len = 2, .vsync_len = 3,
337 .left_margin = 69, .upper_margin = 14,
338 .right_margin = 8, .lower_margin = 4,
339
340 .lccr0 = LCCR0_Color | LCCR0_Sngl | LCCR0_Act,
341 .lccr3 = LCCR3_OutEnH | LCCR3_PixFlEdg | LCCR3_ACBsDiv(512),
342};
343#endif
344#ifdef LART_VIDEO_OUT
345static struct sa1100fb_mach_info lart_video_info __initdata = {
346 .pixclock = 39721, .bpp = 16,
347 .xres = 640, .yres = 480,
348
349 .hsync_len = 95, .vsync_len = 2,
350 .left_margin = 40, .upper_margin = 32,
351 .right_margin = 24, .lower_margin = 11,
352
353 .sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
354
355 .lccr0 = LCCR0_Color | LCCR0_Sngl | LCCR0_Act,
356 .lccr3 = LCCR3_OutEnL | LCCR3_PixFlEdg | LCCR3_ACBsDiv(512),
357};
358#endif
359
360#ifdef LART_KIT01_LCD
361static struct sa1100fb_mach_info lart_kit01_info __initdata = {
362 .pixclock = 63291, .bpp = 16,
363 .xres = 640, .yres = 480,
364
365 .hsync_len = 64, .vsync_len = 3,
366 .left_margin = 122, .upper_margin = 45,
367 .right_margin = 10, .lower_margin = 10,
368
369 .lccr0 = LCCR0_Color | LCCR0_Sngl | LCCR0_Act,
370 .lccr3 = LCCR3_OutEnH | LCCR3_PixFlEdg
371};
372#endif
373
374#ifdef CONFIG_SA1100_SHANNON
375static struct sa1100fb_mach_info shannon_info __initdata = {
376 .pixclock = 152500, .bpp = 8,
377 .xres = 640, .yres = 480,
378
379 .hsync_len = 4, .vsync_len = 3,
380 .left_margin = 2, .upper_margin = 0,
381 .right_margin = 1, .lower_margin = 0,
382
383 .sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
384
385 .lccr0 = LCCR0_Color | LCCR0_Dual | LCCR0_Pas,
386 .lccr3 = LCCR3_ACBsDiv(512),
387};
388#endif
389
390 216
391 217
392static struct sa1100fb_mach_info * __init
393sa1100fb_get_machine_info(struct sa1100fb_info *fbi)
394{
395 struct sa1100fb_mach_info *inf = NULL;
396
397 /*
398 * R G B T
399 * default {11,5}, { 5,6}, { 0,5}, { 0,0}
400 * h3600 {12,4}, { 7,4}, { 1,4}, { 0,0}
401 * freebird { 8,4}, { 4,4}, { 0,4}, {12,4}
402 */
403#ifdef CONFIG_SA1100_ASSABET
404 if (machine_is_assabet()) {
405#ifndef ASSABET_PAL_VIDEO
406 inf = &lq039q2ds54_info;
407#else
408 inf = &pal_info;
409#endif
410 }
411#endif
412#ifdef CONFIG_SA1100_H3100
413 if (machine_is_h3100()) {
414 inf = &h3100_info;
415 }
416#endif
417#ifdef CONFIG_SA1100_H3600
418 if (machine_is_h3600()) {
419 inf = &h3600_info;
420 fbi->rgb[RGB_16] = &h3600_rgb_16;
421 }
422#endif
423#ifdef CONFIG_SA1100_COLLIE
424 if (machine_is_collie()) {
425 inf = &collie_info;
426 }
427#endif
428#ifdef CONFIG_SA1100_LART
429 if (machine_is_lart()) {
430#ifdef LART_GREY_LCD
431 inf = &lart_grey_info;
432#endif
433#ifdef LART_COLOR_LCD
434 inf = &lart_color_info;
435#endif
436#ifdef LART_VIDEO_OUT
437 inf = &lart_video_info;
438#endif
439#ifdef LART_KIT01_LCD
440 inf = &lart_kit01_info;
441#endif
442 }
443#endif
444#ifdef CONFIG_SA1100_SHANNON
445 if (machine_is_shannon()) {
446 inf = &shannon_info;
447 }
448#endif
449 return inf;
450}
451
452static int sa1100fb_activate_var(struct fb_var_screeninfo *var, struct sa1100fb_info *); 218static int sa1100fb_activate_var(struct fb_var_screeninfo *var, struct sa1100fb_info *);
453static void set_ctrlr_state(struct sa1100fb_info *fbi, u_int state); 219static void set_ctrlr_state(struct sa1100fb_info *fbi, u_int state);
454 220
@@ -533,7 +299,7 @@ sa1100fb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
533 * is what you poke into the framebuffer to produce the 299 * is what you poke into the framebuffer to produce the
534 * colour you requested. 300 * colour you requested.
535 */ 301 */
536 if (fbi->cmap_inverse) { 302 if (fbi->inf->cmap_inverse) {
537 red = 0xffff - red; 303 red = 0xffff - red;
538 green = 0xffff - green; 304 green = 0xffff - green;
539 blue = 0xffff - blue; 305 blue = 0xffff - blue;
@@ -607,14 +373,14 @@ sa1100fb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
607 var->xres = MIN_XRES; 373 var->xres = MIN_XRES;
608 if (var->yres < MIN_YRES) 374 if (var->yres < MIN_YRES)
609 var->yres = MIN_YRES; 375 var->yres = MIN_YRES;
610 if (var->xres > fbi->max_xres) 376 if (var->xres > fbi->inf->xres)
611 var->xres = fbi->max_xres; 377 var->xres = fbi->inf->xres;
612 if (var->yres > fbi->max_yres) 378 if (var->yres > fbi->inf->yres)
613 var->yres = fbi->max_yres; 379 var->yres = fbi->inf->yres;
614 var->xres_virtual = max(var->xres_virtual, var->xres); 380 var->xres_virtual = max(var->xres_virtual, var->xres);
615 var->yres_virtual = max(var->yres_virtual, var->yres); 381 var->yres_virtual = max(var->yres_virtual, var->yres);
616 382
617 DPRINTK("var->bits_per_pixel=%d\n", var->bits_per_pixel); 383 dev_dbg(fbi->dev, "var->bits_per_pixel=%d\n", var->bits_per_pixel);
618 switch (var->bits_per_pixel) { 384 switch (var->bits_per_pixel) {
619 case 4: 385 case 4:
620 rgbidx = RGB_4; 386 rgbidx = RGB_4;
@@ -638,16 +404,16 @@ sa1100fb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
638 var->blue = fbi->rgb[rgbidx]->blue; 404 var->blue = fbi->rgb[rgbidx]->blue;
639 var->transp = fbi->rgb[rgbidx]->transp; 405 var->transp = fbi->rgb[rgbidx]->transp;
640 406
641 DPRINTK("RGBT length = %d:%d:%d:%d\n", 407 dev_dbg(fbi->dev, "RGBT length = %d:%d:%d:%d\n",
642 var->red.length, var->green.length, var->blue.length, 408 var->red.length, var->green.length, var->blue.length,
643 var->transp.length); 409 var->transp.length);
644 410
645 DPRINTK("RGBT offset = %d:%d:%d:%d\n", 411 dev_dbg(fbi->dev, "RGBT offset = %d:%d:%d:%d\n",
646 var->red.offset, var->green.offset, var->blue.offset, 412 var->red.offset, var->green.offset, var->blue.offset,
647 var->transp.offset); 413 var->transp.offset);
648 414
649#ifdef CONFIG_CPU_FREQ 415#ifdef CONFIG_CPU_FREQ
650 printk(KERN_DEBUG "dma period = %d ps, clock = %d kHz\n", 416 dev_dbg(fbi->dev, "dma period = %d ps, clock = %d kHz\n",
651 sa1100fb_display_dma_period(var), 417 sa1100fb_display_dma_period(var),
652 cpufreq_get(smp_processor_id())); 418 cpufreq_get(smp_processor_id()));
653#endif 419#endif
@@ -655,22 +421,10 @@ sa1100fb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
655 return 0; 421 return 0;
656} 422}
657 423
658static inline void sa1100fb_set_truecolor(u_int is_true_color) 424static void sa1100fb_set_visual(struct sa1100fb_info *fbi, u32 visual)
659{ 425{
660 if (machine_is_assabet()) { 426 if (fbi->inf->set_visual)
661#if 1 // phase 4 or newer Assabet's 427 fbi->inf->set_visual(visual);
662 if (is_true_color)
663 ASSABET_BCR_set(ASSABET_BCR_LCD_12RGB);
664 else
665 ASSABET_BCR_clear(ASSABET_BCR_LCD_12RGB);
666#else
667 // older Assabet's
668 if (is_true_color)
669 ASSABET_BCR_clear(ASSABET_BCR_LCD_12RGB);
670 else
671 ASSABET_BCR_set(ASSABET_BCR_LCD_12RGB);
672#endif
673 }
674} 428}
675 429
676/* 430/*
@@ -683,11 +437,11 @@ static int sa1100fb_set_par(struct fb_info *info)
683 struct fb_var_screeninfo *var = &info->var; 437 struct fb_var_screeninfo *var = &info->var;
684 unsigned long palette_mem_size; 438 unsigned long palette_mem_size;
685 439
686 DPRINTK("set_par\n"); 440 dev_dbg(fbi->dev, "set_par\n");
687 441
688 if (var->bits_per_pixel == 16) 442 if (var->bits_per_pixel == 16)
689 fbi->fb.fix.visual = FB_VISUAL_TRUECOLOR; 443 fbi->fb.fix.visual = FB_VISUAL_TRUECOLOR;
690 else if (!fbi->cmap_static) 444 else if (!fbi->inf->cmap_static)
691 fbi->fb.fix.visual = FB_VISUAL_PSEUDOCOLOR; 445 fbi->fb.fix.visual = FB_VISUAL_PSEUDOCOLOR;
692 else { 446 else {
693 /* 447 /*
@@ -704,7 +458,7 @@ static int sa1100fb_set_par(struct fb_info *info)
704 458
705 palette_mem_size = fbi->palette_size * sizeof(u16); 459 palette_mem_size = fbi->palette_size * sizeof(u16);
706 460
707 DPRINTK("palette_mem_size = 0x%08lx\n", (u_long) palette_mem_size); 461 dev_dbg(fbi->dev, "palette_mem_size = 0x%08lx\n", palette_mem_size);
708 462
709 fbi->palette_cpu = (u16 *)(fbi->map_cpu + PAGE_SIZE - palette_mem_size); 463 fbi->palette_cpu = (u16 *)(fbi->map_cpu + PAGE_SIZE - palette_mem_size);
710 fbi->palette_dma = fbi->map_dma + PAGE_SIZE - palette_mem_size; 464 fbi->palette_dma = fbi->map_dma + PAGE_SIZE - palette_mem_size;
@@ -712,7 +466,7 @@ static int sa1100fb_set_par(struct fb_info *info)
712 /* 466 /*
713 * Set (any) board control register to handle new color depth 467 * Set (any) board control register to handle new color depth
714 */ 468 */
715 sa1100fb_set_truecolor(fbi->fb.fix.visual == FB_VISUAL_TRUECOLOR); 469 sa1100fb_set_visual(fbi, fbi->fb.fix.visual);
716 sa1100fb_activate_var(var, fbi); 470 sa1100fb_activate_var(var, fbi);
717 471
718 return 0; 472 return 0;
@@ -728,7 +482,7 @@ sa1100fb_set_cmap(struct fb_cmap *cmap, int kspc, int con,
728 /* 482 /*
729 * Make sure the user isn't doing something stupid. 483 * Make sure the user isn't doing something stupid.
730 */ 484 */
731 if (!kspc && (fbi->fb.var.bits_per_pixel == 16 || fbi->cmap_static)) 485 if (!kspc && (fbi->fb.var.bits_per_pixel == 16 || fbi->inf->cmap_static))
732 return -EINVAL; 486 return -EINVAL;
733 487
734 return gen_set_cmap(cmap, kspc, con, info); 488 return gen_set_cmap(cmap, kspc, con, info);
@@ -775,7 +529,7 @@ static int sa1100fb_blank(int blank, struct fb_info *info)
775 struct sa1100fb_info *fbi = (struct sa1100fb_info *)info; 529 struct sa1100fb_info *fbi = (struct sa1100fb_info *)info;
776 int i; 530 int i;
777 531
778 DPRINTK("sa1100fb_blank: blank=%d\n", blank); 532 dev_dbg(fbi->dev, "sa1100fb_blank: blank=%d\n", blank);
779 533
780 switch (blank) { 534 switch (blank) {
781 case FB_BLANK_POWERDOWN: 535 case FB_BLANK_POWERDOWN:
@@ -863,43 +617,43 @@ static int sa1100fb_activate_var(struct fb_var_screeninfo *var, struct sa1100fb_
863 u_int half_screen_size, yres, pcd; 617 u_int half_screen_size, yres, pcd;
864 u_long flags; 618 u_long flags;
865 619
866 DPRINTK("Configuring SA1100 LCD\n"); 620 dev_dbg(fbi->dev, "Configuring SA1100 LCD\n");
867 621
868 DPRINTK("var: xres=%d hslen=%d lm=%d rm=%d\n", 622 dev_dbg(fbi->dev, "var: xres=%d hslen=%d lm=%d rm=%d\n",
869 var->xres, var->hsync_len, 623 var->xres, var->hsync_len,
870 var->left_margin, var->right_margin); 624 var->left_margin, var->right_margin);
871 DPRINTK("var: yres=%d vslen=%d um=%d bm=%d\n", 625 dev_dbg(fbi->dev, "var: yres=%d vslen=%d um=%d bm=%d\n",
872 var->yres, var->vsync_len, 626 var->yres, var->vsync_len,
873 var->upper_margin, var->lower_margin); 627 var->upper_margin, var->lower_margin);
874 628
875#if DEBUG_VAR 629#if DEBUG_VAR
876 if (var->xres < 16 || var->xres > 1024) 630 if (var->xres < 16 || var->xres > 1024)
877 printk(KERN_ERR "%s: invalid xres %d\n", 631 dev_err(fbi->dev, "%s: invalid xres %d\n",
878 fbi->fb.fix.id, var->xres); 632 fbi->fb.fix.id, var->xres);
879 if (var->hsync_len < 1 || var->hsync_len > 64) 633 if (var->hsync_len < 1 || var->hsync_len > 64)
880 printk(KERN_ERR "%s: invalid hsync_len %d\n", 634 dev_err(fbi->dev, "%s: invalid hsync_len %d\n",
881 fbi->fb.fix.id, var->hsync_len); 635 fbi->fb.fix.id, var->hsync_len);
882 if (var->left_margin < 1 || var->left_margin > 255) 636 if (var->left_margin < 1 || var->left_margin > 255)
883 printk(KERN_ERR "%s: invalid left_margin %d\n", 637 dev_err(fbi->dev, "%s: invalid left_margin %d\n",
884 fbi->fb.fix.id, var->left_margin); 638 fbi->fb.fix.id, var->left_margin);
885 if (var->right_margin < 1 || var->right_margin > 255) 639 if (var->right_margin < 1 || var->right_margin > 255)
886 printk(KERN_ERR "%s: invalid right_margin %d\n", 640 dev_err(fbi->dev, "%s: invalid right_margin %d\n",
887 fbi->fb.fix.id, var->right_margin); 641 fbi->fb.fix.id, var->right_margin);
888 if (var->yres < 1 || var->yres > 1024) 642 if (var->yres < 1 || var->yres > 1024)
889 printk(KERN_ERR "%s: invalid yres %d\n", 643 dev_err(fbi->dev, "%s: invalid yres %d\n",
890 fbi->fb.fix.id, var->yres); 644 fbi->fb.fix.id, var->yres);
891 if (var->vsync_len < 1 || var->vsync_len > 64) 645 if (var->vsync_len < 1 || var->vsync_len > 64)
892 printk(KERN_ERR "%s: invalid vsync_len %d\n", 646 dev_err(fbi->dev, "%s: invalid vsync_len %d\n",
893 fbi->fb.fix.id, var->vsync_len); 647 fbi->fb.fix.id, var->vsync_len);
894 if (var->upper_margin < 0 || var->upper_margin > 255) 648 if (var->upper_margin < 0 || var->upper_margin > 255)
895 printk(KERN_ERR "%s: invalid upper_margin %d\n", 649 dev_err(fbi->dev, "%s: invalid upper_margin %d\n",
896 fbi->fb.fix.id, var->upper_margin); 650 fbi->fb.fix.id, var->upper_margin);
897 if (var->lower_margin < 0 || var->lower_margin > 255) 651 if (var->lower_margin < 0 || var->lower_margin > 255)
898 printk(KERN_ERR "%s: invalid lower_margin %d\n", 652 dev_err(fbi->dev, "%s: invalid lower_margin %d\n",
899 fbi->fb.fix.id, var->lower_margin); 653 fbi->fb.fix.id, var->lower_margin);
900#endif 654#endif
901 655
902 new_regs.lccr0 = fbi->lccr0 | 656 new_regs.lccr0 = fbi->inf->lccr0 |
903 LCCR0_LEN | LCCR0_LDM | LCCR0_BAM | 657 LCCR0_LEN | LCCR0_LDM | LCCR0_BAM |
904 LCCR0_ERM | LCCR0_LtlEnd | LCCR0_DMADel(0); 658 LCCR0_ERM | LCCR0_LtlEnd | LCCR0_DMADel(0);
905 659
@@ -914,7 +668,7 @@ static int sa1100fb_activate_var(struct fb_var_screeninfo *var, struct sa1100fb_
914 * the YRES parameter. 668 * the YRES parameter.
915 */ 669 */
916 yres = var->yres; 670 yres = var->yres;
917 if (fbi->lccr0 & LCCR0_Dual) 671 if (fbi->inf->lccr0 & LCCR0_Dual)
918 yres /= 2; 672 yres /= 2;
919 673
920 new_regs.lccr2 = 674 new_regs.lccr2 =
@@ -924,14 +678,14 @@ static int sa1100fb_activate_var(struct fb_var_screeninfo *var, struct sa1100fb_
924 LCCR2_EndFrmDel(var->lower_margin); 678 LCCR2_EndFrmDel(var->lower_margin);
925 679
926 pcd = get_pcd(var->pixclock, cpufreq_get(0)); 680 pcd = get_pcd(var->pixclock, cpufreq_get(0));
927 new_regs.lccr3 = LCCR3_PixClkDiv(pcd) | fbi->lccr3 | 681 new_regs.lccr3 = LCCR3_PixClkDiv(pcd) | fbi->inf->lccr3 |
928 (var->sync & FB_SYNC_HOR_HIGH_ACT ? LCCR3_HorSnchH : LCCR3_HorSnchL) | 682 (var->sync & FB_SYNC_HOR_HIGH_ACT ? LCCR3_HorSnchH : LCCR3_HorSnchL) |
929 (var->sync & FB_SYNC_VERT_HIGH_ACT ? LCCR3_VrtSnchH : LCCR3_VrtSnchL); 683 (var->sync & FB_SYNC_VERT_HIGH_ACT ? LCCR3_VrtSnchH : LCCR3_VrtSnchL);
930 684
931 DPRINTK("nlccr0 = 0x%08lx\n", new_regs.lccr0); 685 dev_dbg(fbi->dev, "nlccr0 = 0x%08lx\n", new_regs.lccr0);
932 DPRINTK("nlccr1 = 0x%08lx\n", new_regs.lccr1); 686 dev_dbg(fbi->dev, "nlccr1 = 0x%08lx\n", new_regs.lccr1);
933 DPRINTK("nlccr2 = 0x%08lx\n", new_regs.lccr2); 687 dev_dbg(fbi->dev, "nlccr2 = 0x%08lx\n", new_regs.lccr2);
934 DPRINTK("nlccr3 = 0x%08lx\n", new_regs.lccr3); 688 dev_dbg(fbi->dev, "nlccr3 = 0x%08lx\n", new_regs.lccr3);
935 689
936 half_screen_size = var->bits_per_pixel; 690 half_screen_size = var->bits_per_pixel;
937 half_screen_size = half_screen_size * var->xres * var->yres / 16; 691 half_screen_size = half_screen_size * var->xres * var->yres / 16;
@@ -951,9 +705,12 @@ static int sa1100fb_activate_var(struct fb_var_screeninfo *var, struct sa1100fb_
951 * Only update the registers if the controller is enabled 705 * Only update the registers if the controller is enabled
952 * and something has changed. 706 * and something has changed.
953 */ 707 */
954 if ((LCCR0 != fbi->reg_lccr0) || (LCCR1 != fbi->reg_lccr1) || 708 if (readl_relaxed(fbi->base + LCCR0) != fbi->reg_lccr0 ||
955 (LCCR2 != fbi->reg_lccr2) || (LCCR3 != fbi->reg_lccr3) || 709 readl_relaxed(fbi->base + LCCR1) != fbi->reg_lccr1 ||
956 (DBAR1 != fbi->dbar1) || (DBAR2 != fbi->dbar2)) 710 readl_relaxed(fbi->base + LCCR2) != fbi->reg_lccr2 ||
711 readl_relaxed(fbi->base + LCCR3) != fbi->reg_lccr3 ||
712 readl_relaxed(fbi->base + DBAR1) != fbi->dbar1 ||
713 readl_relaxed(fbi->base + DBAR2) != fbi->dbar2)
957 sa1100fb_schedule_work(fbi, C_REENABLE); 714 sa1100fb_schedule_work(fbi, C_REENABLE);
958 715
959 return 0; 716 return 0;
@@ -967,18 +724,18 @@ static int sa1100fb_activate_var(struct fb_var_screeninfo *var, struct sa1100fb_
967 */ 724 */
968static inline void __sa1100fb_backlight_power(struct sa1100fb_info *fbi, int on) 725static inline void __sa1100fb_backlight_power(struct sa1100fb_info *fbi, int on)
969{ 726{
970 DPRINTK("backlight o%s\n", on ? "n" : "ff"); 727 dev_dbg(fbi->dev, "backlight o%s\n", on ? "n" : "ff");
971 728
972 if (sa1100fb_backlight_power) 729 if (fbi->inf->backlight_power)
973 sa1100fb_backlight_power(on); 730 fbi->inf->backlight_power(on);
974} 731}
975 732
976static inline void __sa1100fb_lcd_power(struct sa1100fb_info *fbi, int on) 733static inline void __sa1100fb_lcd_power(struct sa1100fb_info *fbi, int on)
977{ 734{
978 DPRINTK("LCD power o%s\n", on ? "n" : "ff"); 735 dev_dbg(fbi->dev, "LCD power o%s\n", on ? "n" : "ff");
979 736
980 if (sa1100fb_lcd_power) 737 if (fbi->inf->lcd_power)
981 sa1100fb_lcd_power(on); 738 fbi->inf->lcd_power(on);
982} 739}
983 740
984static void sa1100fb_setup_gpio(struct sa1100fb_info *fbi) 741static void sa1100fb_setup_gpio(struct sa1100fb_info *fbi)
@@ -1008,14 +765,25 @@ static void sa1100fb_setup_gpio(struct sa1100fb_info *fbi)
1008 } 765 }
1009 766
1010 if (mask) { 767 if (mask) {
768 unsigned long flags;
769
770 /*
771 * SA-1100 requires the GPIO direction register set
772 * appropriately for the alternate function. Hence
773 * we set it here via bitmask rather than excessive
774 * fiddling via the GPIO subsystem - and even then
775 * we'll still have to deal with GAFR.
776 */
777 local_irq_save(flags);
1011 GPDR |= mask; 778 GPDR |= mask;
1012 GAFR |= mask; 779 GAFR |= mask;
780 local_irq_restore(flags);
1013 } 781 }
1014} 782}
1015 783
1016static void sa1100fb_enable_controller(struct sa1100fb_info *fbi) 784static void sa1100fb_enable_controller(struct sa1100fb_info *fbi)
1017{ 785{
1018 DPRINTK("Enabling LCD controller\n"); 786 dev_dbg(fbi->dev, "Enabling LCD controller\n");
1019 787
1020 /* 788 /*
1021 * Make sure the mode bits are present in the first palette entry 789 * Make sure the mode bits are present in the first palette entry
@@ -1024,43 +792,46 @@ static void sa1100fb_enable_controller(struct sa1100fb_info *fbi)
1024 fbi->palette_cpu[0] |= palette_pbs(&fbi->fb.var); 792 fbi->palette_cpu[0] |= palette_pbs(&fbi->fb.var);
1025 793
1026 /* Sequence from 11.7.10 */ 794 /* Sequence from 11.7.10 */
1027 LCCR3 = fbi->reg_lccr3; 795 writel_relaxed(fbi->reg_lccr3, fbi->base + LCCR3);
1028 LCCR2 = fbi->reg_lccr2; 796 writel_relaxed(fbi->reg_lccr2, fbi->base + LCCR2);
1029 LCCR1 = fbi->reg_lccr1; 797 writel_relaxed(fbi->reg_lccr1, fbi->base + LCCR1);
1030 LCCR0 = fbi->reg_lccr0 & ~LCCR0_LEN; 798 writel_relaxed(fbi->reg_lccr0 & ~LCCR0_LEN, fbi->base + LCCR0);
1031 DBAR1 = fbi->dbar1; 799 writel_relaxed(fbi->dbar1, fbi->base + DBAR1);
1032 DBAR2 = fbi->dbar2; 800 writel_relaxed(fbi->dbar2, fbi->base + DBAR2);
1033 LCCR0 |= LCCR0_LEN; 801 writel_relaxed(fbi->reg_lccr0 | LCCR0_LEN, fbi->base + LCCR0);
1034 802
1035 if (machine_is_shannon()) { 803 if (machine_is_shannon())
1036 GPDR |= SHANNON_GPIO_DISP_EN; 804 gpio_set_value(SHANNON_GPIO_DISP_EN, 1);
1037 GPSR |= SHANNON_GPIO_DISP_EN; 805
1038 } 806 dev_dbg(fbi->dev, "DBAR1: 0x%08x\n", readl_relaxed(fbi->base + DBAR1));
1039 807 dev_dbg(fbi->dev, "DBAR2: 0x%08x\n", readl_relaxed(fbi->base + DBAR2));
1040 DPRINTK("DBAR1 = 0x%08x\n", DBAR1); 808 dev_dbg(fbi->dev, "LCCR0: 0x%08x\n", readl_relaxed(fbi->base + LCCR0));
1041 DPRINTK("DBAR2 = 0x%08x\n", DBAR2); 809 dev_dbg(fbi->dev, "LCCR1: 0x%08x\n", readl_relaxed(fbi->base + LCCR1));
1042 DPRINTK("LCCR0 = 0x%08x\n", LCCR0); 810 dev_dbg(fbi->dev, "LCCR2: 0x%08x\n", readl_relaxed(fbi->base + LCCR2));
1043 DPRINTK("LCCR1 = 0x%08x\n", LCCR1); 811 dev_dbg(fbi->dev, "LCCR3: 0x%08x\n", readl_relaxed(fbi->base + LCCR3));
1044 DPRINTK("LCCR2 = 0x%08x\n", LCCR2);
1045 DPRINTK("LCCR3 = 0x%08x\n", LCCR3);
1046} 812}
1047 813
1048static void sa1100fb_disable_controller(struct sa1100fb_info *fbi) 814static void sa1100fb_disable_controller(struct sa1100fb_info *fbi)
1049{ 815{
1050 DECLARE_WAITQUEUE(wait, current); 816 DECLARE_WAITQUEUE(wait, current);
817 u32 lccr0;
1051 818
1052 DPRINTK("Disabling LCD controller\n"); 819 dev_dbg(fbi->dev, "Disabling LCD controller\n");
1053 820
1054 if (machine_is_shannon()) { 821 if (machine_is_shannon())
1055 GPCR |= SHANNON_GPIO_DISP_EN; 822 gpio_set_value(SHANNON_GPIO_DISP_EN, 0);
1056 }
1057 823
1058 set_current_state(TASK_UNINTERRUPTIBLE); 824 set_current_state(TASK_UNINTERRUPTIBLE);
1059 add_wait_queue(&fbi->ctrlr_wait, &wait); 825 add_wait_queue(&fbi->ctrlr_wait, &wait);
1060 826
1061 LCSR = 0xffffffff; /* Clear LCD Status Register */ 827 /* Clear LCD Status Register */
1062 LCCR0 &= ~LCCR0_LDM; /* Enable LCD Disable Done Interrupt */ 828 writel_relaxed(~0, fbi->base + LCSR);
1063 LCCR0 &= ~LCCR0_LEN; /* Disable LCD Controller */ 829
830 lccr0 = readl_relaxed(fbi->base + LCCR0);
831 lccr0 &= ~LCCR0_LDM; /* Enable LCD Disable Done Interrupt */
832 writel_relaxed(lccr0, fbi->base + LCCR0);
833 lccr0 &= ~LCCR0_LEN; /* Disable LCD Controller */
834 writel_relaxed(lccr0, fbi->base + LCCR0);
1064 835
1065 schedule_timeout(20 * HZ / 1000); 836 schedule_timeout(20 * HZ / 1000);
1066 remove_wait_queue(&fbi->ctrlr_wait, &wait); 837 remove_wait_queue(&fbi->ctrlr_wait, &wait);
@@ -1072,14 +843,15 @@ static void sa1100fb_disable_controller(struct sa1100fb_info *fbi)
1072static irqreturn_t sa1100fb_handle_irq(int irq, void *dev_id) 843static irqreturn_t sa1100fb_handle_irq(int irq, void *dev_id)
1073{ 844{
1074 struct sa1100fb_info *fbi = dev_id; 845 struct sa1100fb_info *fbi = dev_id;
1075 unsigned int lcsr = LCSR; 846 unsigned int lcsr = readl_relaxed(fbi->base + LCSR);
1076 847
1077 if (lcsr & LCSR_LDD) { 848 if (lcsr & LCSR_LDD) {
1078 LCCR0 |= LCCR0_LDM; 849 u32 lccr0 = readl_relaxed(fbi->base + LCCR0) | LCCR0_LDM;
850 writel_relaxed(lccr0, fbi->base + LCCR0);
1079 wake_up(&fbi->ctrlr_wait); 851 wake_up(&fbi->ctrlr_wait);
1080 } 852 }
1081 853
1082 LCSR = lcsr; 854 writel_relaxed(lcsr, fbi->base + LCSR);
1083 return IRQ_HANDLED; 855 return IRQ_HANDLED;
1084} 856}
1085 857
@@ -1268,7 +1040,7 @@ sa1100fb_freq_policy(struct notifier_block *nb, unsigned long val,
1268 switch (val) { 1040 switch (val) {
1269 case CPUFREQ_ADJUST: 1041 case CPUFREQ_ADJUST:
1270 case CPUFREQ_INCOMPATIBLE: 1042 case CPUFREQ_INCOMPATIBLE:
1271 printk(KERN_DEBUG "min dma period: %d ps, " 1043 dev_dbg(fbi->dev, "min dma period: %d ps, "
1272 "new clock %d kHz\n", sa1100fb_min_dma_period(fbi), 1044 "new clock %d kHz\n", sa1100fb_min_dma_period(fbi),
1273 policy->max); 1045 policy->max);
1274 /* todo: fill in min/max values */ 1046 /* todo: fill in min/max values */
@@ -1318,7 +1090,7 @@ static int sa1100fb_resume(struct platform_device *dev)
1318 * cache. Once this area is remapped, all virtual memory 1090 * cache. Once this area is remapped, all virtual memory
1319 * access to the video memory should occur at the new region. 1091 * access to the video memory should occur at the new region.
1320 */ 1092 */
1321static int __init sa1100fb_map_video_memory(struct sa1100fb_info *fbi) 1093static int __devinit sa1100fb_map_video_memory(struct sa1100fb_info *fbi)
1322{ 1094{
1323 /* 1095 /*
1324 * We reserve one page for the palette, plus the size 1096 * We reserve one page for the palette, plus the size
@@ -1344,7 +1116,7 @@ static int __init sa1100fb_map_video_memory(struct sa1100fb_info *fbi)
1344} 1116}
1345 1117
1346/* Fake monspecs to fill in fbinfo structure */ 1118/* Fake monspecs to fill in fbinfo structure */
1347static struct fb_monspecs monspecs __initdata = { 1119static struct fb_monspecs monspecs __devinitdata = {
1348 .hfmin = 30000, 1120 .hfmin = 30000,
1349 .hfmax = 70000, 1121 .hfmax = 70000,
1350 .vfmin = 50, 1122 .vfmin = 50,
@@ -1352,10 +1124,11 @@ static struct fb_monspecs monspecs __initdata = {
1352}; 1124};
1353 1125
1354 1126
1355static struct sa1100fb_info * __init sa1100fb_init_fbinfo(struct device *dev) 1127static struct sa1100fb_info * __devinit sa1100fb_init_fbinfo(struct device *dev)
1356{ 1128{
1357 struct sa1100fb_mach_info *inf; 1129 struct sa1100fb_mach_info *inf = dev->platform_data;
1358 struct sa1100fb_info *fbi; 1130 struct sa1100fb_info *fbi;
1131 unsigned i;
1359 1132
1360 fbi = kmalloc(sizeof(struct sa1100fb_info) + sizeof(u32) * 16, 1133 fbi = kmalloc(sizeof(struct sa1100fb_info) + sizeof(u32) * 16,
1361 GFP_KERNEL); 1134 GFP_KERNEL);
@@ -1390,8 +1163,6 @@ static struct sa1100fb_info * __init sa1100fb_init_fbinfo(struct device *dev)
1390 fbi->rgb[RGB_8] = &rgb_8; 1163 fbi->rgb[RGB_8] = &rgb_8;
1391 fbi->rgb[RGB_16] = &def_rgb_16; 1164 fbi->rgb[RGB_16] = &def_rgb_16;
1392 1165
1393 inf = sa1100fb_get_machine_info(fbi);
1394
1395 /* 1166 /*
1396 * People just don't seem to get this. We don't support 1167 * People just don't seem to get this. We don't support
1397 * anything but correct entries now, so panic if someone 1168 * anything but correct entries now, so panic if someone
@@ -1402,13 +1173,10 @@ static struct sa1100fb_info * __init sa1100fb_init_fbinfo(struct device *dev)
1402 panic("sa1100fb error: invalid LCCR3 fields set or zero " 1173 panic("sa1100fb error: invalid LCCR3 fields set or zero "
1403 "pixclock."); 1174 "pixclock.");
1404 1175
1405 fbi->max_xres = inf->xres;
1406 fbi->fb.var.xres = inf->xres; 1176 fbi->fb.var.xres = inf->xres;
1407 fbi->fb.var.xres_virtual = inf->xres; 1177 fbi->fb.var.xres_virtual = inf->xres;
1408 fbi->max_yres = inf->yres;
1409 fbi->fb.var.yres = inf->yres; 1178 fbi->fb.var.yres = inf->yres;
1410 fbi->fb.var.yres_virtual = inf->yres; 1179 fbi->fb.var.yres_virtual = inf->yres;
1411 fbi->max_bpp = inf->bpp;
1412 fbi->fb.var.bits_per_pixel = inf->bpp; 1180 fbi->fb.var.bits_per_pixel = inf->bpp;
1413 fbi->fb.var.pixclock = inf->pixclock; 1181 fbi->fb.var.pixclock = inf->pixclock;
1414 fbi->fb.var.hsync_len = inf->hsync_len; 1182 fbi->fb.var.hsync_len = inf->hsync_len;
@@ -1419,14 +1187,16 @@ static struct sa1100fb_info * __init sa1100fb_init_fbinfo(struct device *dev)
1419 fbi->fb.var.lower_margin = inf->lower_margin; 1187 fbi->fb.var.lower_margin = inf->lower_margin;
1420 fbi->fb.var.sync = inf->sync; 1188 fbi->fb.var.sync = inf->sync;
1421 fbi->fb.var.grayscale = inf->cmap_greyscale; 1189 fbi->fb.var.grayscale = inf->cmap_greyscale;
1422 fbi->cmap_inverse = inf->cmap_inverse;
1423 fbi->cmap_static = inf->cmap_static;
1424 fbi->lccr0 = inf->lccr0;
1425 fbi->lccr3 = inf->lccr3;
1426 fbi->state = C_STARTUP; 1190 fbi->state = C_STARTUP;
1427 fbi->task_state = (u_char)-1; 1191 fbi->task_state = (u_char)-1;
1428 fbi->fb.fix.smem_len = fbi->max_xres * fbi->max_yres * 1192 fbi->fb.fix.smem_len = inf->xres * inf->yres *
1429 fbi->max_bpp / 8; 1193 inf->bpp / 8;
1194 fbi->inf = inf;
1195
1196 /* Copy the RGB bitfield overrides */
1197 for (i = 0; i < NR_RGB; i++)
1198 if (inf->rgb[i])
1199 fbi->rgb[i] = inf->rgb[i];
1430 1200
1431 init_waitqueue_head(&fbi->ctrlr_wait); 1201 init_waitqueue_head(&fbi->ctrlr_wait);
1432 INIT_WORK(&fbi->task, sa1100fb_task); 1202 INIT_WORK(&fbi->task, sa1100fb_task);
@@ -1438,13 +1208,20 @@ static struct sa1100fb_info * __init sa1100fb_init_fbinfo(struct device *dev)
1438static int __devinit sa1100fb_probe(struct platform_device *pdev) 1208static int __devinit sa1100fb_probe(struct platform_device *pdev)
1439{ 1209{
1440 struct sa1100fb_info *fbi; 1210 struct sa1100fb_info *fbi;
1211 struct resource *res;
1441 int ret, irq; 1212 int ret, irq;
1442 1213
1214 if (!pdev->dev.platform_data) {
1215 dev_err(&pdev->dev, "no platform LCD data\n");
1216 return -EINVAL;
1217 }
1218
1219 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
1443 irq = platform_get_irq(pdev, 0); 1220 irq = platform_get_irq(pdev, 0);
1444 if (irq < 0) 1221 if (irq < 0 || !res)
1445 return -EINVAL; 1222 return -EINVAL;
1446 1223
1447 if (!request_mem_region(0xb0100000, 0x10000, "LCD")) 1224 if (!request_mem_region(res->start, resource_size(res), "LCD"))
1448 return -EBUSY; 1225 return -EBUSY;
1449 1226
1450 fbi = sa1100fb_init_fbinfo(&pdev->dev); 1227 fbi = sa1100fb_init_fbinfo(&pdev->dev);
@@ -1452,6 +1229,10 @@ static int __devinit sa1100fb_probe(struct platform_device *pdev)
1452 if (!fbi) 1229 if (!fbi)
1453 goto failed; 1230 goto failed;
1454 1231
1232 fbi->base = ioremap(res->start, resource_size(res));
1233 if (!fbi->base)
1234 goto failed;
1235
1455 /* Initialize video memory */ 1236 /* Initialize video memory */
1456 ret = sa1100fb_map_video_memory(fbi); 1237 ret = sa1100fb_map_video_memory(fbi);
1457 if (ret) 1238 if (ret)
@@ -1459,14 +1240,16 @@ static int __devinit sa1100fb_probe(struct platform_device *pdev)
1459 1240
1460 ret = request_irq(irq, sa1100fb_handle_irq, 0, "LCD", fbi); 1241 ret = request_irq(irq, sa1100fb_handle_irq, 0, "LCD", fbi);
1461 if (ret) { 1242 if (ret) {
1462 printk(KERN_ERR "sa1100fb: request_irq failed: %d\n", ret); 1243 dev_err(&pdev->dev, "request_irq failed: %d\n", ret);
1463 goto failed; 1244 goto failed;
1464 } 1245 }
1465 1246
1466#ifdef ASSABET_PAL_VIDEO 1247 if (machine_is_shannon()) {
1467 if (machine_is_assabet()) 1248 ret = gpio_request_one(SHANNON_GPIO_DISP_EN,
1468 ASSABET_BCR_clear(ASSABET_BCR_LCD_ON); 1249 GPIOF_OUT_INIT_LOW, "display enable");
1469#endif 1250 if (ret)
1251 goto err_free_irq;
1252 }
1470 1253
1471 /* 1254 /*
1472 * This makes sure that our colour bitfield 1255 * This makes sure that our colour bitfield
@@ -1478,7 +1261,7 @@ static int __devinit sa1100fb_probe(struct platform_device *pdev)
1478 1261
1479 ret = register_framebuffer(&fbi->fb); 1262 ret = register_framebuffer(&fbi->fb);
1480 if (ret < 0) 1263 if (ret < 0)
1481 goto err_free_irq; 1264 goto err_reg_fb;
1482 1265
1483#ifdef CONFIG_CPU_FREQ 1266#ifdef CONFIG_CPU_FREQ
1484 fbi->freq_transition.notifier_call = sa1100fb_freq_transition; 1267 fbi->freq_transition.notifier_call = sa1100fb_freq_transition;
@@ -1490,12 +1273,17 @@ static int __devinit sa1100fb_probe(struct platform_device *pdev)
1490 /* This driver cannot be unloaded at the moment */ 1273 /* This driver cannot be unloaded at the moment */
1491 return 0; 1274 return 0;
1492 1275
1276 err_reg_fb:
1277 if (machine_is_shannon())
1278 gpio_free(SHANNON_GPIO_DISP_EN);
1493 err_free_irq: 1279 err_free_irq:
1494 free_irq(irq, fbi); 1280 free_irq(irq, fbi);
1495 failed: 1281 failed:
1282 if (fbi)
1283 iounmap(fbi->base);
1496 platform_set_drvdata(pdev, NULL); 1284 platform_set_drvdata(pdev, NULL);
1497 kfree(fbi); 1285 kfree(fbi);
1498 release_mem_region(0xb0100000, 0x10000); 1286 release_mem_region(res->start, resource_size(res));
1499 return ret; 1287 return ret;
1500} 1288}
1501 1289
@@ -1505,6 +1293,7 @@ static struct platform_driver sa1100fb_driver = {
1505 .resume = sa1100fb_resume, 1293 .resume = sa1100fb_resume,
1506 .driver = { 1294 .driver = {
1507 .name = "sa11x0-fb", 1295 .name = "sa11x0-fb",
1296 .owner = THIS_MODULE,
1508 }, 1297 },
1509}; 1298};
1510 1299
diff --git a/drivers/video/sa1100fb.h b/drivers/video/sa1100fb.h
index 1c3b459865d8..fc5d4292fad6 100644
--- a/drivers/video/sa1100fb.h
+++ b/drivers/video/sa1100fb.h
@@ -10,44 +10,15 @@
10 * for more details. 10 * for more details.
11 */ 11 */
12 12
13/* 13#define LCCR0 0x0000 /* LCD Control Reg. 0 */
14 * These are the bitfields for each 14#define LCSR 0x0004 /* LCD Status Reg. */
15 * display depth that we support. 15#define DBAR1 0x0010 /* LCD DMA Base Address Reg. channel 1 */
16 */ 16#define DCAR1 0x0014 /* LCD DMA Current Address Reg. channel 1 */
17struct sa1100fb_rgb { 17#define DBAR2 0x0018 /* LCD DMA Base Address Reg. channel 2 */
18 struct fb_bitfield red; 18#define DCAR2 0x001C /* LCD DMA Current Address Reg. channel 2 */
19 struct fb_bitfield green; 19#define LCCR1 0x0020 /* LCD Control Reg. 1 */
20 struct fb_bitfield blue; 20#define LCCR2 0x0024 /* LCD Control Reg. 2 */
21 struct fb_bitfield transp; 21#define LCCR3 0x0028 /* LCD Control Reg. 3 */
22};
23
24/*
25 * This structure describes the machine which we are running on.
26 */
27struct sa1100fb_mach_info {
28 u_long pixclock;
29
30 u_short xres;
31 u_short yres;
32
33 u_char bpp;
34 u_char hsync_len;
35 u_char left_margin;
36 u_char right_margin;
37
38 u_char vsync_len;
39 u_char upper_margin;
40 u_char lower_margin;
41 u_char sync;
42
43 u_int cmap_greyscale:1,
44 cmap_inverse:1,
45 cmap_static:1,
46 unused:29;
47
48 u_int lccr0;
49 u_int lccr3;
50};
51 22
52/* Shadows for LCD controller registers */ 23/* Shadows for LCD controller registers */
53struct sa1100fb_lcd_reg { 24struct sa1100fb_lcd_reg {
@@ -57,19 +28,11 @@ struct sa1100fb_lcd_reg {
57 unsigned long lccr3; 28 unsigned long lccr3;
58}; 29};
59 30
60#define RGB_4 (0)
61#define RGB_8 (1)
62#define RGB_16 (2)
63#define NR_RGB 3
64
65struct sa1100fb_info { 31struct sa1100fb_info {
66 struct fb_info fb; 32 struct fb_info fb;
67 struct device *dev; 33 struct device *dev;
68 struct sa1100fb_rgb *rgb[NR_RGB]; 34 const struct sa1100fb_rgb *rgb[NR_RGB];
69 35 void __iomem *base;
70 u_int max_bpp;
71 u_int max_xres;
72 u_int max_yres;
73 36
74 /* 37 /*
75 * These are the addresses we mapped 38 * These are the addresses we mapped
@@ -88,12 +51,6 @@ struct sa1100fb_info {
88 dma_addr_t dbar1; 51 dma_addr_t dbar1;
89 dma_addr_t dbar2; 52 dma_addr_t dbar2;
90 53
91 u_int lccr0;
92 u_int lccr3;
93 u_int cmap_inverse:1,
94 cmap_static:1,
95 unused:30;
96
97 u_int reg_lccr0; 54 u_int reg_lccr0;
98 u_int reg_lccr1; 55 u_int reg_lccr1;
99 u_int reg_lccr2; 56 u_int reg_lccr2;
@@ -109,6 +66,8 @@ struct sa1100fb_info {
109 struct notifier_block freq_transition; 66 struct notifier_block freq_transition;
110 struct notifier_block freq_policy; 67 struct notifier_block freq_policy;
111#endif 68#endif
69
70 const struct sa1100fb_mach_info *inf;
112}; 71};
113 72
114#define TO_INF(ptr,member) container_of(ptr,struct sa1100fb_info,member) 73#define TO_INF(ptr,member) container_of(ptr,struct sa1100fb_info,member)
@@ -130,15 +89,6 @@ struct sa1100fb_info {
130#define SA1100_NAME "SA1100" 89#define SA1100_NAME "SA1100"
131 90
132/* 91/*
133 * Debug macros
134 */
135#if DEBUG
136# define DPRINTK(fmt, args...) printk("%s: " fmt, __func__ , ## args)
137#else
138# define DPRINTK(fmt, args...)
139#endif
140
141/*
142 * Minimum X and Y resolutions 92 * Minimum X and Y resolutions
143 */ 93 */
144#define MIN_XRES 64 94#define MIN_XRES 64
diff --git a/include/video/sa1100fb.h b/include/video/sa1100fb.h
new file mode 100644
index 000000000000..4ab409653785
--- /dev/null
+++ b/include/video/sa1100fb.h
@@ -0,0 +1,63 @@
1/*
2 * StrongARM 1100 LCD Controller Frame Buffer Device
3 *
4 * Copyright (C) 1999 Eric A. Thomas
5 * Based on acornfb.c Copyright (C) Russell King.
6 *
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
9 * for more details.
10 */
11#ifndef _VIDEO_SA1100FB_H
12#define _VIDEO_SA1100FB_H
13
14#include <linux/fb.h>
15#include <linux/types.h>
16
17#define RGB_4 0
18#define RGB_8 1
19#define RGB_16 2
20#define NR_RGB 3
21
22/* These are the bitfields for each display depth that we support. */
23struct sa1100fb_rgb {
24 struct fb_bitfield red;
25 struct fb_bitfield green;
26 struct fb_bitfield blue;
27 struct fb_bitfield transp;
28};
29
30/* This structure describes the machine which we are running on. */
31struct sa1100fb_mach_info {
32 u_long pixclock;
33
34 u_short xres;
35 u_short yres;
36
37 u_char bpp;
38 u_char hsync_len;
39 u_char left_margin;
40 u_char right_margin;
41
42 u_char vsync_len;
43 u_char upper_margin;
44 u_char lower_margin;
45 u_char sync;
46
47 u_int cmap_greyscale:1,
48 cmap_inverse:1,
49 cmap_static:1,
50 unused:29;
51
52 u_int lccr0;
53 u_int lccr3;
54
55 /* Overrides for the default RGB maps */
56 const struct sa1100fb_rgb *rgb[NR_RGB];
57
58 void (*backlight_power)(int);
59 void (*lcd_power)(int);
60 void (*set_visual)(u32);
61};
62
63#endif