diff --git a/arch/arm/mach-pxa/corgi_lcd.c b/arch/arm/mach-pxa/corgi_lcd.c
index 6dbcaf114ad782a00907b15672f9ae60aff0dfea..d7815491b752cb3e344bff363cb023c2adf7ea8c 100644
--- a/arch/arm/mach-pxa/corgi_lcd.c
+++ b/arch/arm/mach-pxa/corgi_lcd.c
@@ -431,10 +431,10 @@ struct platform_device corgifb_device = {
 
 #include <asm/arch/pxafb.h>
 
-void spitz_lcd_power(int on)
+void spitz_lcd_power(int on, struct fb_var_screeninfo *var)
 {
 	if (on)
-		lcdtg_hw_init(480);
+		lcdtg_hw_init(var->xres);
 	else
 		lcdtg_suspend();
 }
diff --git a/arch/arm/mach-pxa/generic.c b/arch/arm/mach-pxa/generic.c
index 5efa84749f374fae50ade0adfcb67c5b8bacf494..45fb2c3bcf828f3812adf0b95675d77256487c05 100644
--- a/arch/arm/mach-pxa/generic.c
+++ b/arch/arm/mach-pxa/generic.c
@@ -204,13 +204,6 @@ static struct platform_device udc_device = {
 	}
 };
 
-static struct pxafb_mach_info pxa_fb_info;
-
-void __init set_pxa_fb_info(struct pxafb_mach_info *hard_pxa_fb_info)
-{
-	memcpy(&pxa_fb_info,hard_pxa_fb_info,sizeof(struct pxafb_mach_info));
-}
-
 static struct resource pxafb_resources[] = {
 	[0] = {
 		.start	= 0x44000000,
@@ -230,7 +223,6 @@ static struct platform_device pxafb_device = {
 	.name		= "pxa2xx-fb",
 	.id		= -1,
 	.dev		= {
- 		.platform_data	= &pxa_fb_info,
 		.dma_mask	= &fb_dma_mask,
 		.coherent_dma_mask = 0xffffffff,
 	},
@@ -238,6 +230,11 @@ static struct platform_device pxafb_device = {
 	.resource	= pxafb_resources,
 };
 
+void __init set_pxa_fb_info(struct pxafb_mach_info *info)
+{
+	pxafb_device.dev.platform_data = info;
+}
+
 void __init set_pxa_fb_parent(struct device *parent_dev)
 {
 	pxafb_device.dev.parent = parent_dev;
diff --git a/arch/arm/mach-pxa/idp.c b/arch/arm/mach-pxa/idp.c
index 6914d22bc20fbfb0b19c8eba67f48e0e85ef83ad..3e4b0ab71c66bbe40530ef03935d29126b3942e8 100644
--- a/arch/arm/mach-pxa/idp.c
+++ b/arch/arm/mach-pxa/idp.c
@@ -82,7 +82,7 @@ static void idp_vlcd(int on)
 	}
 }
 
-static void idp_lcd_power(int on)
+static void idp_lcd_power(int on, struct fb_var_screeninfo *var)
 {
 	if (on) {
 		IDP_CPLD_LCD |= (1<<0);
@@ -99,7 +99,7 @@ static void idp_lcd_power(int on)
 	idp_vlcd(on);
 }
 
-static struct pxafb_mach_info sharp_lm8v31 __initdata = {
+static struct pxafb_mode_info sharp_lm8v31_mode = {
 	.pixclock	= 270000,
 	.xres		= 640,
 	.yres		= 480,
@@ -112,6 +112,11 @@ static struct pxafb_mach_info sharp_lm8v31 __initdata = {
 	.lower_margin	= 0,
 	.sync		= FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
 	.cmap_greyscale	= 0,
+};
+
+static struct pxafb_mach_info sharp_lm8v31 = {
+	.modes          = &sharp_lm8v31_mode,
+	.num_modes      = 1,
 	.cmap_inverse	= 0,
 	.cmap_static	= 0,
 	.lccr0		= LCCR0_SDS,
diff --git a/arch/arm/mach-pxa/lpd270.c b/arch/arm/mach-pxa/lpd270.c
index 12479ae26db2addc8c4bcd5f1a11a40d563f24e4..eff2a91b2565ee8b46d3673c6bbe5d12759e2c1f 100644
--- a/arch/arm/mach-pxa/lpd270.c
+++ b/arch/arm/mach-pxa/lpd270.c
@@ -248,7 +248,7 @@ static void lpd270_backlight_power(int on)
 }
 
 /* 5.7" TFT QVGA (LoLo display number 1) */
-static struct pxafb_mach_info sharp_lq057q3dc02 __initdata = {
+static struct pxafb_mode_info sharp_lq057q3dc02_mode = {
 	.pixclock		= 150000,
 	.xres			= 320,
 	.yres			= 240,
@@ -260,13 +260,18 @@ static struct pxafb_mach_info sharp_lq057q3dc02 __initdata = {
 	.upper_margin		= 0x08,
 	.lower_margin		= 0x14,
 	.sync			= FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+};
+
+static struct pxafb_mach_info sharp_lq057q3dc02 = {
+	.modes			= &sharp_lq057q3dc02_mode,
+	.num_modes		= 1,
 	.lccr0			= 0x07800080,
 	.lccr3			= 0x00400000,
 	.pxafb_backlight_power	= lpd270_backlight_power,
 };
 
 /* 12.1" TFT SVGA (LoLo display number 2) */
-static struct pxafb_mach_info sharp_lq121s1dg31 __initdata = {
+static struct pxafb_mode_info sharp_lq121s1dg31_mode = {
 	.pixclock		= 50000,
 	.xres			= 800,
 	.yres			= 600,
@@ -278,13 +283,18 @@ static struct pxafb_mach_info sharp_lq121s1dg31 __initdata = {
 	.upper_margin		= 0x14,
 	.lower_margin		= 0x0a,
 	.sync			= FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+};
+
+static struct pxafb_mach_info sharp_lq121s1dg31 = {
+	.modes			= &sharp_lq121s1dg31_mode,
+	.num_modes		= 1,
 	.lccr0			= 0x07800080,
 	.lccr3			= 0x00400000,
 	.pxafb_backlight_power	= lpd270_backlight_power,
 };
 
 /* 3.6" TFT QVGA (LoLo display number 3) */
-static struct pxafb_mach_info sharp_lq036q1da01 __initdata = {
+static struct pxafb_mode_info sharp_lq036q1da01_mode = {
 	.pixclock		= 150000,
 	.xres			= 320,
 	.yres			= 240,
@@ -296,13 +306,18 @@ static struct pxafb_mach_info sharp_lq036q1da01 __initdata = {
 	.upper_margin		= 0x03,
 	.lower_margin		= 0x03,
 	.sync			= FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+};
+
+static struct pxafb_mach_info sharp_lq036q1da01 = {
+	.modes			= &sharp_lq036q1da01_mode,
+	.num_modes		= 1,
 	.lccr0			= 0x07800080,
 	.lccr3			= 0x00400000,
 	.pxafb_backlight_power	= lpd270_backlight_power,
 };
 
 /* 6.4" TFT VGA (LoLo display number 5) */
-static struct pxafb_mach_info sharp_lq64d343 __initdata = {
+static struct pxafb_mode_info sharp_lq64d343_mode = {
 	.pixclock		= 25000,
 	.xres			= 640,
 	.yres			= 480,
@@ -314,13 +329,18 @@ static struct pxafb_mach_info sharp_lq64d343 __initdata = {
 	.upper_margin		= 0x22,
 	.lower_margin		= 0x00,
 	.sync			= FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+};
+
+static struct pxafb_mach_info sharp_lq64d343 = {
+	.modes			= &sharp_lq64d343_mode,
+	.num_modes		= 1,
 	.lccr0			= 0x07800080,
 	.lccr3			= 0x00400000,
 	.pxafb_backlight_power	= lpd270_backlight_power,
 };
 
 /* 10.4" TFT VGA (LoLo display number 7) */
-static struct pxafb_mach_info sharp_lq10d368 __initdata = {
+static struct pxafb_mode_info sharp_lq10d368_mode = {
 	.pixclock		= 25000,
 	.xres			= 640,
 	.yres			= 480,
@@ -332,13 +352,18 @@ static struct pxafb_mach_info sharp_lq10d368 __initdata = {
 	.upper_margin		= 0x22,
 	.lower_margin		= 0x00,
 	.sync			= FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+};
+
+static struct pxafb_mach_info sharp_lq10d368 = {
+	.modes			= &sharp_lq10d368_mode,
+	.num_modes		= 1,
 	.lccr0			= 0x07800080,
 	.lccr3			= 0x00400000,
 	.pxafb_backlight_power	= lpd270_backlight_power,
 };
 
 /* 3.5" TFT QVGA (LoLo display number 8) */
-static struct pxafb_mach_info sharp_lq035q7db02_20 __initdata = {
+static struct pxafb_mode_info sharp_lq035q7db02_20_mode = {
 	.pixclock		= 150000,
 	.xres			= 240,
 	.yres			= 320,
@@ -350,6 +375,11 @@ static struct pxafb_mach_info sharp_lq035q7db02_20 __initdata = {
 	.upper_margin		= 0x05,
 	.lower_margin		= 0x14,
 	.sync			= FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+};
+
+static struct pxafb_mach_info sharp_lq035q7db02_20 = {
+	.modes			= &sharp_lq035q7db02_20_mode,
+	.num_modes		= 1,
 	.lccr0			= 0x07800080,
 	.lccr3			= 0x00400000,
 	.pxafb_backlight_power	= lpd270_backlight_power,
diff --git a/arch/arm/mach-pxa/lubbock.c b/arch/arm/mach-pxa/lubbock.c
index 83ff5cee64d935d27396564f78721ff90b2d582b..157cf47cbe6655e239cb7a0c78abe15b4df88788 100644
--- a/arch/arm/mach-pxa/lubbock.c
+++ b/arch/arm/mach-pxa/lubbock.c
@@ -352,7 +352,7 @@ static struct platform_device *devices[] __initdata = {
 	&pxa_ssp,
 };
 
-static struct pxafb_mach_info sharp_lm8v31 __initdata = {
+static struct pxafb_mode_info sharp_lm8v31_mode = {
 	.pixclock	= 270000,
 	.xres		= 640,
 	.yres		= 480,
@@ -365,6 +365,11 @@ static struct pxafb_mach_info sharp_lm8v31 __initdata = {
 	.lower_margin	= 0,
 	.sync		= FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
 	.cmap_greyscale	= 0,
+};
+
+static struct pxafb_mach_info sharp_lm8v31 = {
+	.modes		= &sharp_lm8v31_mode,
+	.num_modes	= 1,
 	.cmap_inverse	= 0,
 	.cmap_static	= 0,
 	.lccr0		= LCCR0_SDS,
diff --git a/arch/arm/mach-pxa/mainstone.c b/arch/arm/mach-pxa/mainstone.c
index a7e9b96f258a4b34e9a209dca6b2f7ddb69e8228..7ba0447d6fa3dfbbb160f3c98e88daa97565dba9 100644
--- a/arch/arm/mach-pxa/mainstone.c
+++ b/arch/arm/mach-pxa/mainstone.c
@@ -279,7 +279,7 @@ static void mainstone_backlight_power(int on)
 	}
 }
 
-static struct pxafb_mach_info toshiba_ltm04c380k __initdata = {
+static struct pxafb_mode_info toshiba_ltm04c380k_mode = {
 	.pixclock		= 50000,
 	.xres			= 640,
 	.yres			= 480,
@@ -291,12 +291,9 @@ static struct pxafb_mach_info toshiba_ltm04c380k __initdata = {
 	.upper_margin		= 0,
 	.lower_margin		= 0,
 	.sync			= FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT,
-	.lccr0			= LCCR0_Act,
-	.lccr3			= LCCR3_PCP,
-	.pxafb_backlight_power	= mainstone_backlight_power,
 };
 
-static struct pxafb_mach_info toshiba_ltm035a776c __initdata = {
+static struct pxafb_mode_info toshiba_ltm035a776c_mode = {
 	.pixclock		= 110000,
 	.xres			= 240,
 	.yres			= 320,
@@ -308,6 +305,10 @@ static struct pxafb_mach_info toshiba_ltm035a776c __initdata = {
 	.upper_margin		= 1,
 	.lower_margin		= 10,
 	.sync			= FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT,
+};
+
+static struct pxafb_mach_info mainstone_pxafb_info = {
+	.num_modes      	= 1,
 	.lccr0			= LCCR0_Act,
 	.lccr3			= LCCR3_PCP,
 	.pxafb_backlight_power	= mainstone_backlight_power,
@@ -448,9 +449,11 @@ static void __init mainstone_init(void)
 	/* reading Mainstone's "Virtual Configuration Register"
 	   might be handy to select LCD type here */
 	if (0)
-		set_pxa_fb_info(&toshiba_ltm04c380k);
+		mainstone_pxafb_info.modes = &toshiba_ltm04c380k_mode;
 	else
-		set_pxa_fb_info(&toshiba_ltm035a776c);
+		mainstone_pxafb_info.modes = &toshiba_ltm035a776c_mode;
+
+	set_pxa_fb_info(&mainstone_pxafb_info);
 
 	pxa_set_mci_info(&mainstone_mci_platform_data);
 	pxa_set_ficp_info(&mainstone_ficp_platform_data);
diff --git a/arch/arm/mach-pxa/poodle.c b/arch/arm/mach-pxa/poodle.c
index 6dbff6d9480172fe0f9209f32587e03a7f56cc26..5e8c098ca13986125b15927bc9b8d2dc0eff1c52 100644
--- a/arch/arm/mach-pxa/poodle.c
+++ b/arch/arm/mach-pxa/poodle.c
@@ -296,27 +296,25 @@ static struct pxa2xx_udc_mach_info udc_info __initdata = {
 
 
 /* PXAFB device */
-static struct pxafb_mach_info poodle_fb_info __initdata = {
+static struct pxafb_mode_info poodle_fb_mode = {
 	.pixclock	= 144700,
-
 	.xres		= 320,
 	.yres		= 240,
 	.bpp		= 16,
-
 	.hsync_len	= 7,
 	.left_margin	= 11,
 	.right_margin	= 30,
-
 	.vsync_len	= 2,
 	.upper_margin	= 2,
 	.lower_margin	= 0,
 	.sync		= FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+};
 
+static struct pxafb_mach_info poodle_fb_info = {
+	.modes		= &poodle_fb_mode,
+	.num_modes	= 1,
 	.lccr0		= LCCR0_Act | LCCR0_Sngl | LCCR0_Color,
 	.lccr3		= 0,
-
-	.pxafb_backlight_power	= NULL,
-	.pxafb_lcd_power	= NULL,
 };
 
 static struct platform_device *devices[] __initdata = {
diff --git a/arch/arm/mach-pxa/spitz.c b/arch/arm/mach-pxa/spitz.c
index 1c32a9310dc27abe5aa43d54d24a7bfdc2a50b62..401cdb850fbc2f014eec92a2a307290b99425eca 100644
--- a/arch/arm/mach-pxa/spitz.c
+++ b/arch/arm/mach-pxa/spitz.c
@@ -407,21 +407,42 @@ static struct pxaficp_platform_data spitz_ficp_platform_data = {
 /*
  * Spitz PXA Framebuffer
  */
-static struct pxafb_mach_info spitz_pxafb_info __initdata = {
-        .pixclock       = 19231,
-        .xres           = 480,
-        .yres           = 640,
-        .bpp            = 16,
-        .hsync_len      = 40,
-        .left_margin    = 46,
-        .right_margin   = 125,
-        .vsync_len      = 3,
-        .upper_margin   = 1,
-        .lower_margin   = 0,
-        .sync           = 0,
-        .lccr0          = LCCR0_Color | LCCR0_Sngl | LCCR0_Act | LCCR0_LDDALT | LCCR0_OUC | LCCR0_CMDIM | LCCR0_RDSTM,
-        .lccr3          = LCCR3_PixRsEdg | LCCR3_OutEnH,
-        .pxafb_lcd_power = spitz_lcd_power,
+
+static struct pxafb_mode_info spitz_pxafb_modes[] = {
+{
+	.pixclock       = 19231,
+	.xres           = 480,
+	.yres           = 640,
+	.bpp            = 16,
+	.hsync_len      = 40,
+	.left_margin    = 46,
+	.right_margin   = 125,
+	.vsync_len      = 3,
+	.upper_margin   = 1,
+	.lower_margin   = 0,
+	.sync           = 0,
+},{
+	.pixclock       = 134617,
+	.xres           = 240,
+	.yres           = 320,
+	.bpp            = 16,
+	.hsync_len      = 20,
+	.left_margin    = 20,
+	.right_margin   = 46,
+	.vsync_len      = 2,
+	.upper_margin   = 1,
+	.lower_margin   = 0,
+	.sync           = 0,
+},
+};
+
+static struct pxafb_mach_info spitz_pxafb_info = {
+	.modes          = &spitz_pxafb_modes[0],
+	.num_modes      = 2,
+	.fixed_modes    = 1,
+	.lccr0          = LCCR0_Color | LCCR0_Sngl | LCCR0_Act | LCCR0_LDDALT | LCCR0_OUC | LCCR0_CMDIM | LCCR0_RDSTM,
+	.lccr3          = LCCR3_PixRsEdg | LCCR3_OutEnH,
+	.pxafb_lcd_power = spitz_lcd_power,
 };
 
 
diff --git a/arch/arm/mach-pxa/trizeps4.c b/arch/arm/mach-pxa/trizeps4.c
index 7c3007df1bd6e22be0c009dd796b5cf69bb89f11..910571e9a190cba0597219ce523c7c97a7525e7d 100644
--- a/arch/arm/mach-pxa/trizeps4.c
+++ b/arch/arm/mach-pxa/trizeps4.c
@@ -368,7 +368,7 @@ static struct map_desc trizeps4_io_desc[] __initdata = {
 	}
 };
 
-static struct pxafb_mach_info sharp_lcd __initdata = {
+static struct pxafb_mode_info sharp_lcd_mode = {
     .pixclock		= 78000,
     .xres		= 640,
     .yres		= 480,
@@ -381,6 +381,11 @@ static struct pxafb_mach_info sharp_lcd __initdata = {
     .lower_margin	= 0,
     .sync		= FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
     .cmap_greyscale	= 0,
+};
+
+static struct pxafb_mach_info sharp_lcd = {
+    .modes		= &sharp_lcd_mode,
+    .num_modes	= 1,
     .cmap_inverse	= 0,
     .cmap_static	= 0,
     .lccr0		= LCCR0_Color | LCCR0_Pas | LCCR0_Dual,
diff --git a/drivers/video/pxafb.c b/drivers/video/pxafb.c
index bbb07106cd54b1b50f2a3de7cf769590a7a56536..3bc5da4a57ca5caeca7046b89cb7b1dbd412a5e0 100644
--- a/drivers/video/pxafb.c
+++ b/drivers/video/pxafb.c
@@ -59,7 +59,7 @@
 #define LCCR3_INVALID_CONFIG_MASK (LCCR3_HSP|LCCR3_VSP|LCCR3_PCD|LCCR3_BPP)
 
 static void (*pxafb_backlight_power)(int);
-static void (*pxafb_lcd_power)(int);
+static void (*pxafb_lcd_power)(int, struct fb_var_screeninfo *);
 
 static int pxafb_activate_var(struct fb_var_screeninfo *var, struct pxafb_info *);
 static void set_ctrlr_state(struct pxafb_info *fbi, u_int state);
@@ -213,6 +213,48 @@ static unsigned int pxafb_display_dma_period(struct fb_var_screeninfo *var)
 extern unsigned int get_clk_frequency_khz(int info);
 #endif
 
+/*
+ * Select the smallest mode that allows the desired resolution to be
+ * displayed. If desired parameters can be rounded up.
+ */
+static struct pxafb_mode_info *pxafb_getmode(struct pxafb_mach_info *mach, struct fb_var_screeninfo *var)
+{
+	struct pxafb_mode_info *mode = NULL;
+	struct pxafb_mode_info *modelist = mach->modes;
+	unsigned int best_x = 0xffffffff, best_y = 0xffffffff;
+	unsigned int i;
+
+	for (i = 0 ; i < mach->num_modes ; i++) {
+		if (modelist[i].xres >= var->xres && modelist[i].yres >= var->yres &&
+				modelist[i].xres < best_x && modelist[i].yres < best_y &&
+				modelist[i].bpp >= var->bits_per_pixel ) {
+			best_x = modelist[i].xres;
+			best_y = modelist[i].yres;
+			mode = &modelist[i];
+		}
+	}
+
+	return mode;
+}
+
+static void pxafb_setmode(struct fb_var_screeninfo *var, struct pxafb_mode_info *mode)
+{
+	var->xres		= mode->xres;
+	var->yres		= mode->yres;
+	var->bits_per_pixel	= mode->bpp;
+	var->pixclock		= mode->pixclock;
+	var->hsync_len		= mode->hsync_len;
+	var->left_margin	= mode->left_margin;
+	var->right_margin	= mode->right_margin;
+	var->vsync_len		= mode->vsync_len;
+	var->upper_margin	= mode->upper_margin;
+	var->lower_margin	= mode->lower_margin;
+	var->sync		= mode->sync;
+	var->grayscale		= mode->cmap_greyscale;
+	var->xres_virtual 	= var->xres;
+	var->yres_virtual	= var->yres;
+}
+
 /*
  *  pxafb_check_var():
  *    Get the video params out of 'var'. If a value doesn't fit, round it up,
@@ -225,15 +267,29 @@ extern unsigned int get_clk_frequency_khz(int info);
 static int pxafb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
 {
 	struct pxafb_info *fbi = (struct pxafb_info *)info;
+	struct pxafb_mach_info *inf = fbi->dev->platform_data;
 
 	if (var->xres < MIN_XRES)
 		var->xres = MIN_XRES;
 	if (var->yres < MIN_YRES)
 		var->yres = MIN_YRES;
-	if (var->xres > fbi->max_xres)
-		return -EINVAL;
-	if (var->yres > fbi->max_yres)
-		return -EINVAL;
+
+	if (inf->fixed_modes) {
+		struct pxafb_mode_info *mode;
+
+		mode = pxafb_getmode(inf, var);
+		if (!mode)
+			return -EINVAL;
+		pxafb_setmode(var, mode);
+	} else {
+		if (var->xres > inf->modes->xres)
+			return -EINVAL;
+		if (var->yres > inf->modes->yres)
+			return -EINVAL;
+		if (var->bits_per_pixel > inf->modes->bpp)
+			return -EINVAL;
+	}
+
 	var->xres_virtual =
 		max(var->xres_virtual, var->xres);
 	var->yres_virtual =
@@ -693,7 +749,7 @@ static inline void __pxafb_lcd_power(struct pxafb_info *fbi, int on)
 	pr_debug("pxafb: LCD power o%s\n", on ? "n" : "ff");
 
 	if (pxafb_lcd_power)
-		pxafb_lcd_power(on);
+		pxafb_lcd_power(on, &fbi->fb.var);
 }
 
 static void pxafb_setup_gpio(struct pxafb_info *fbi)
@@ -869,9 +925,11 @@ static void set_ctrlr_state(struct pxafb_info *fbi, u_int state)
 		 * registers.
 		 */
 		if (old_state == C_ENABLE) {
+			__pxafb_lcd_power(fbi, 0);
 			pxafb_disable_controller(fbi);
 			pxafb_setup_gpio(fbi);
 			pxafb_enable_controller(fbi);
+			__pxafb_lcd_power(fbi, 1);
 		}
 		break;
 
@@ -1049,6 +1107,8 @@ static struct pxafb_info * __init pxafb_init_fbinfo(struct device *dev)
 	struct pxafb_info *fbi;
 	void *addr;
 	struct pxafb_mach_info *inf = dev->platform_data;
+	struct pxafb_mode_info *mode = inf->modes;
+	int i, smemlen;
 
 	/* Alloc the pxafb_info and pseudo_palette in one step */
 	fbi = kmalloc(sizeof(struct pxafb_info) + sizeof(u32) * 16, GFP_KERNEL);
@@ -1082,31 +1142,21 @@ static struct pxafb_info * __init pxafb_init_fbinfo(struct device *dev)
 	addr = addr + sizeof(struct pxafb_info);
 	fbi->fb.pseudo_palette	= addr;
 
-	fbi->max_xres			= inf->xres;
-	fbi->fb.var.xres		= inf->xres;
-	fbi->fb.var.xres_virtual	= inf->xres;
-	fbi->max_yres			= inf->yres;
-	fbi->fb.var.yres		= inf->yres;
-	fbi->fb.var.yres_virtual	= inf->yres;
-	fbi->max_bpp			= inf->bpp;
-	fbi->fb.var.bits_per_pixel	= inf->bpp;
-	fbi->fb.var.pixclock		= inf->pixclock;
-	fbi->fb.var.hsync_len		= inf->hsync_len;
-	fbi->fb.var.left_margin		= inf->left_margin;
-	fbi->fb.var.right_margin	= inf->right_margin;
-	fbi->fb.var.vsync_len		= inf->vsync_len;
-	fbi->fb.var.upper_margin	= inf->upper_margin;
-	fbi->fb.var.lower_margin	= inf->lower_margin;
-	fbi->fb.var.sync		= inf->sync;
-	fbi->fb.var.grayscale		= inf->cmap_greyscale;
+	pxafb_setmode(&fbi->fb.var, mode);
+
 	fbi->cmap_inverse		= inf->cmap_inverse;
 	fbi->cmap_static		= inf->cmap_static;
+
 	fbi->lccr0			= inf->lccr0;
 	fbi->lccr3			= inf->lccr3;
 	fbi->state			= C_STARTUP;
 	fbi->task_state			= (u_char)-1;
-	fbi->fb.fix.smem_len		= fbi->max_xres * fbi->max_yres *
-					  fbi->max_bpp / 8;
+
+	for (i = 0; i < inf->num_modes; i++) {
+		smemlen = mode[i].xres * mode[i].yres * mode[i].bpp / 8;
+		if (smemlen > fbi->fb.fix.smem_len)
+			fbi->fb.fix.smem_len = smemlen;
+	}
 
 	init_waitqueue_head(&fbi->ctrlr_wait);
 	INIT_WORK(&fbi->task, pxafb_task, fbi);
@@ -1307,12 +1357,12 @@ int __init pxafb_probe(struct platform_device *dev)
 	    (inf->lccr0 & LCCR0_SDS) == LCCR0_Dual)
                 dev_warn(&dev->dev, "Dual panel only valid in passive mode\n");
         if ((inf->lccr0 & LCCR0_PAS) == LCCR0_Pas &&
-             (inf->upper_margin || inf->lower_margin))
+             (inf->modes->upper_margin || inf->modes->lower_margin))
                 dev_warn(&dev->dev, "Upper and lower margins must be 0 in passive mode\n");
 #endif
 
-	dev_dbg(&dev->dev, "got a %dx%dx%d LCD\n",inf->xres, inf->yres, inf->bpp);
-	if (inf->xres == 0 || inf->yres == 0 || inf->bpp == 0) {
+	dev_dbg(&dev->dev, "got a %dx%dx%d LCD\n",inf->modes->xres, inf->modes->yres, inf->modes->bpp);
+	if (inf->modes->xres == 0 || inf->modes->yres == 0 || inf->modes->bpp == 0) {
 		dev_err(&dev->dev, "Invalid resolution or bit depth\n");
 		ret = -EINVAL;
 		goto failed;
diff --git a/drivers/video/pxafb.h b/drivers/video/pxafb.h
index 47f41f70db7a042c821ddc65832529487364f26b..7499a1c4bf790c9ecf51ba7093878080284facb6 100644
--- a/drivers/video/pxafb.h
+++ b/drivers/video/pxafb.h
@@ -41,10 +41,6 @@ struct pxafb_info {
 	struct fb_info		fb;
 	struct device		*dev;
 
-	u_int			max_bpp;
-	u_int			max_xres;
-	u_int			max_yres;
-
 	/*
 	 * These are the addresses we mapped
 	 * the framebuffer memory region to.
diff --git a/include/asm-arm/arch-pxa/pxafb.h b/include/asm-arm/arch-pxa/pxafb.h
index aba9b30f42490cbcfe6aab1e090662755cf0b913..81c3928d608c8182dae4d266d67ad247f119e845 100644
--- a/include/asm-arm/arch-pxa/pxafb.h
+++ b/include/asm-arm/arch-pxa/pxafb.h
@@ -12,12 +12,14 @@
  *  published by the Free Software Foundation.
  */
 
+#include <linux/fb.h>
+
 /*
  * This structure describes the machine which we are running on.
  * It is set in linux/arch/arm/mach-pxa/machine_name.c and used in the probe routine
  * of linux/drivers/video/pxafb.c
  */
-struct pxafb_mach_info {
+struct pxafb_mode_info {
 	u_long		pixclock;
 
 	u_short		xres;
@@ -34,6 +36,14 @@ struct pxafb_mach_info {
 	u_char		sync;
 
 	u_int		cmap_greyscale:1,
+			unused:31;
+};
+
+struct pxafb_mach_info {
+	struct pxafb_mode_info *modes;
+	unsigned int num_modes;
+
+	u_int		fixed_modes:1,
 			cmap_inverse:1,
 			cmap_static:1,
 			unused:29;
@@ -62,7 +72,7 @@ struct pxafb_mach_info {
 	u_int		lccr3;
 
 	void (*pxafb_backlight_power)(int);
-	void (*pxafb_lcd_power)(int);
+	void (*pxafb_lcd_power)(int, struct fb_var_screeninfo *);
 
 };
 void set_pxa_fb_info(struct pxafb_mach_info *hard_pxa_fb_info);
diff --git a/include/asm-arm/arch-pxa/spitz.h b/include/asm-arm/arch-pxa/spitz.h
index 62e1fe4d025f96a6f527d09e4a8ed20e705333fa..4953dd324d4d1e51630c48bce3d15eaf05a3a426 100644
--- a/include/asm-arm/arch-pxa/spitz.h
+++ b/include/asm-arm/arch-pxa/spitz.h
@@ -15,6 +15,8 @@
 #define __ASM_ARCH_SPITZ_H  1
 #endif
 
+#include <linux/fb.h>
+
 /* Spitz/Akita GPIOs */
 
 #define SPITZ_GPIO_KEY_INT         (0) /* Key Interrupt */
@@ -155,4 +157,4 @@ extern struct platform_device spitzscoop2_device;
 extern struct platform_device spitzssp_device;
 extern struct sharpsl_charger_machinfo spitz_pm_machinfo;
 
-extern void spitz_lcd_power(int on);
+extern void spitz_lcd_power(int on, struct fb_var_screeninfo *var);