Browse Source

Merge branch 'devel' of git://git.kernel.org/pub/scm/linux/kernel/git/ycmiao/pxa-linux-2.6 into devel-stable

Conflicts:
	arch/arm/mach-pxa/tosa.c
Russell King 14 years ago
parent
commit
938c0ace3f
51 changed files with 514 additions and 582 deletions
  1. 0 2
      arch/arm/include/asm/mach/udc_pxa2xx.h
  2. 4 4
      arch/arm/mach-pxa/am200epd.c
  3. 7 6
      arch/arm/mach-pxa/am300epd.c
  4. 1 1
      arch/arm/mach-pxa/balloon3.c
  5. 1 1
      arch/arm/mach-pxa/cm-x2xx.c
  6. 1 1
      arch/arm/mach-pxa/cm-x300.c
  7. 1 1
      arch/arm/mach-pxa/colibri-pxa270-income.c
  8. 1 1
      arch/arm/mach-pxa/colibri-pxa3xx.c
  9. 0 1
      arch/arm/mach-pxa/corgi.c
  10. 2 7
      arch/arm/mach-pxa/devices.c
  11. 1 1
      arch/arm/mach-pxa/em-x270.c
  12. 27 9
      arch/arm/mach-pxa/eseries.c
  13. 6 6
      arch/arm/mach-pxa/ezx.c
  14. 11 2
      arch/arm/mach-pxa/gumstix.c
  15. 1 1
      arch/arm/mach-pxa/idp.c
  16. 5 0
      arch/arm/mach-pxa/include/mach/palmz72.h
  17. 2 2
      arch/arm/mach-pxa/include/mach/pxafb.h
  18. 1 2
      arch/arm/mach-pxa/include/mach/z2.h
  19. 1 1
      arch/arm/mach-pxa/littleton.c
  20. 1 1
      arch/arm/mach-pxa/lpd270.c
  21. 1 1
      arch/arm/mach-pxa/lubbock.c
  22. 1 1
      arch/arm/mach-pxa/magician.c
  23. 1 1
      arch/arm/mach-pxa/mainstone.c
  24. 1 1
      arch/arm/mach-pxa/mioa701.c
  25. 2 3
      arch/arm/mach-pxa/palm27x.c
  26. 1 1
      arch/arm/mach-pxa/palmtc.c
  27. 8 25
      arch/arm/mach-pxa/palmte2.c
  28. 127 0
      arch/arm/mach-pxa/palmz72.c
  29. 1 1
      arch/arm/mach-pxa/pcm990-baseboard.c
  30. 1 2
      arch/arm/mach-pxa/poodle.c
  31. 1 1
      arch/arm/mach-pxa/raumfeld.c
  32. 1 1
      arch/arm/mach-pxa/saar.c
  33. 1 1
      arch/arm/mach-pxa/spitz.c
  34. 1 1
      arch/arm/mach-pxa/tavorevb.c
  35. 2 3
      arch/arm/mach-pxa/time.c
  36. 11 2
      arch/arm/mach-pxa/tosa.c
  37. 2 2
      arch/arm/mach-pxa/trizeps4.c
  38. 1 1
      arch/arm/mach-pxa/viper.c
  39. 1 1
      arch/arm/mach-pxa/vpac270.c
  40. 38 39
      arch/arm/mach-pxa/z2.c
  41. 1 1
      arch/arm/mach-pxa/zeus.c
  42. 2 2
      arch/arm/mach-pxa/zylonite.c
  43. 22 21
      drivers/ata/pata_palmld.c
  44. 49 84
      drivers/pcmcia/pxa2xx_colibri.c
  45. 10 32
      drivers/pcmcia/pxa2xx_palmld.c
  46. 13 62
      drivers/pcmcia/pxa2xx_palmtc.c
  47. 12 45
      drivers/pcmcia/pxa2xx_palmtx.c
  48. 30 80
      drivers/pcmcia/pxa2xx_vpac270.c
  49. 7 69
      drivers/usb/gadget/pxa25x_udc.c
  50. 89 47
      drivers/video/pxafb.c
  51. 2 1
      drivers/video/pxafb.h

+ 0 - 2
arch/arm/include/asm/mach/udc_pxa2xx.h

@@ -20,8 +20,6 @@ struct pxa2xx_udc_mach_info {
 	 * VBUS IRQ and omit the methods above.  Store the GPIO number
 	 * here.  Note that sometimes the signals go through inverters...
 	 */
-	bool	gpio_vbus_inverted;
-	int	gpio_vbus;			/* high == vbus present */
 	bool	gpio_pullup_inverted;
 	int	gpio_pullup;			/* high == pullup activated */
 };

+ 4 - 4
arch/arm/mach-pxa/am200epd.c

@@ -128,8 +128,8 @@ static int am200_init_gpio_regs(struct metronomefb_par *par)
 	return 0;
 
 err_req_gpio:
-	while (i > 0)
-		gpio_free(gpios[i--]);
+	while (--i >= 0)
+		gpio_free(gpios[i]);
 
 	return err;
 }
@@ -194,7 +194,7 @@ static struct notifier_block am200_fb_notif = {
 };
 
 /* this gets called as part of our init. these steps must be done now so
- * that we can use set_pxa_fb_info */
+ * that we can use pxa_set_fb_info */
 static void __init am200_presetup_fb(void)
 {
 	int fw;
@@ -249,7 +249,7 @@ static void __init am200_presetup_fb(void)
 	/* we divide since we told the LCD controller we're 16bpp */
 	am200_fb_info.modes->xres /= 2;
 
-	set_pxa_fb_info(&am200_fb_info);
+	pxa_set_fb_info(NULL, &am200_fb_info);
 
 }
 

+ 7 - 6
arch/arm/mach-pxa/am300epd.c

@@ -125,10 +125,7 @@ static int am300_init_gpio_regs(struct broadsheetfb_par *par)
 		if (err) {
 			dev_err(&am300_device->dev, "failed requesting "
 				"gpio %d, err=%d\n", i, err);
-			while (i >= DB0_GPIO_PIN)
-				gpio_free(i--);
-			i = ARRAY_SIZE(gpios) - 1;
-			goto err_req_gpio;
+			goto err_req_gpio2;
 		}
 	}
 
@@ -159,9 +156,13 @@ static int am300_init_gpio_regs(struct broadsheetfb_par *par)
 
 	return 0;
 
+err_req_gpio2:
+	while (--i >= DB0_GPIO_PIN)
+		gpio_free(i);
+	i = ARRAY_SIZE(gpios);
 err_req_gpio:
-	while (i > 0)
-		gpio_free(gpios[i--]);
+	while (--i >= 0)
+		gpio_free(gpios[i]);
 
 	return err;
 }

+ 1 - 1
arch/arm/mach-pxa/balloon3.c

@@ -263,7 +263,7 @@ static void __init balloon3_lcd_init(void)
 	}
 
 	balloon3_lcd_screen.pxafb_backlight_power = balloon3_backlight_power;
-	set_pxa_fb_info(&balloon3_lcd_screen);
+	pxa_set_fb_info(NULL, &balloon3_lcd_screen);
 	return;
 
 err2:

+ 1 - 1
arch/arm/mach-pxa/cm-x2xx.c

@@ -379,7 +379,7 @@ __setup("monitor=", cmx2xx_set_display);
 
 static void __init cmx2xx_init_display(void)
 {
-	set_pxa_fb_info(cmx2xx_display);
+	pxa_set_fb_info(NULL, cmx2xx_display);
 }
 #else
 static inline void cmx2xx_init_display(void) {}

+ 1 - 1
arch/arm/mach-pxa/cm-x300.c

@@ -296,7 +296,7 @@ static struct pxafb_mach_info cm_x300_lcd = {
 
 static void __init cm_x300_init_lcd(void)
 {
-	set_pxa_fb_info(&cm_x300_lcd);
+	pxa_set_fb_info(NULL, &cm_x300_lcd);
 }
 #else
 static inline void cm_x300_init_lcd(void) {}

+ 1 - 1
arch/arm/mach-pxa/colibri-pxa270-income.c

@@ -175,7 +175,7 @@ static struct pxafb_mach_info income_lcd_screen = {
 
 static void __init income_lcd_init(void)
 {
-	set_pxa_fb_info(&income_lcd_screen);
+	pxa_set_fb_info(NULL, &income_lcd_screen);
 }
 #else
 static inline void income_lcd_init(void) {}

+ 1 - 1
arch/arm/mach-pxa/colibri-pxa3xx.c

@@ -105,7 +105,7 @@ void __init colibri_pxa3xx_init_lcd(int bl_pin)
 	lcd_bl_pin = bl_pin;
 	gpio_request(bl_pin, "lcd backlight");
 	gpio_direction_output(bl_pin, 0);
-	set_pxa_fb_info(&sharp_lq43_info);
+	pxa_set_fb_info(NULL, &sharp_lq43_info);
 }
 #endif
 

+ 0 - 1
arch/arm/mach-pxa/corgi.c

@@ -462,7 +462,6 @@ static struct pxaficp_platform_data corgi_ficp_platform_data = {
  * USB Device Controller
  */
 static struct pxa2xx_udc_mach_info udc_info __initdata = {
-	.gpio_vbus		= -1,
 	/* no connect GPIO; corgi can't tell connection status */
 	.gpio_pullup		= CORGI_GPIO_USB_PULLUP,
 };

+ 2 - 7
arch/arm/mach-pxa/devices.c

@@ -90,7 +90,6 @@ void __init pxa_set_mci_info(struct pxamci_platform_data *info)
 
 static struct pxa2xx_udc_mach_info pxa_udc_info = {
 	.gpio_pullup = -1,
-	.gpio_vbus   = -1,
 };
 
 void __init pxa_set_udc_info(struct pxa2xx_udc_mach_info *info)
@@ -188,16 +187,12 @@ struct platform_device pxa_device_fb = {
 	.resource	= pxafb_resources,
 };
 
-void __init set_pxa_fb_info(struct pxafb_mach_info *info)
+void __init pxa_set_fb_info(struct device *parent, struct pxafb_mach_info *info)
 {
+	pxa_device_fb.dev.parent = parent;
 	pxa_register_device(&pxa_device_fb, info);
 }
 
-void __init set_pxa_fb_parent(struct device *parent_dev)
-{
-	pxa_device_fb.dev.parent = parent_dev;
-}
-
 static struct resource pxa_resource_ffuart[] = {
 	{
 		.start	= 0x40100000,

+ 1 - 1
arch/arm/mach-pxa/em-x270.c

@@ -689,7 +689,7 @@ static struct pxafb_mach_info em_x270_lcd = {
 
 static void __init em_x270_init_lcd(void)
 {
-	set_pxa_fb_info(&em_x270_lcd);
+	pxa_set_fb_info(NULL, &em_x270_lcd);
 }
 #else
 static inline void em_x270_init_lcd(void) {}

+ 27 - 9
arch/arm/mach-pxa/eseries.c

@@ -20,6 +20,7 @@
 #include <linux/mfd/t7l66xb.h>
 #include <linux/mtd/nand.h>
 #include <linux/mtd/partitions.h>
+#include <linux/usb/gpio_vbus.h>
 
 #include <video/w100fb.h>
 
@@ -51,12 +52,20 @@ void __init eseries_fixup(struct machine_desc *desc,
 		mi->bank[0].size = (64*1024*1024);
 }
 
-struct pxa2xx_udc_mach_info e7xx_udc_mach_info = {
+struct gpio_vbus_mach_info e7xx_udc_info = {
 	.gpio_vbus   = GPIO_E7XX_USB_DISC,
 	.gpio_pullup = GPIO_E7XX_USB_PULLUP,
 	.gpio_pullup_inverted = 1
 };
 
+static struct platform_device e7xx_gpio_vbus = {
+	.name	= "gpio-vbus",
+	.id	= -1,
+	.dev	= {
+		.platform_data	= &e7xx_udc_info,
+	},
+};
+
 struct pxaficp_platform_data e7xx_ficp_platform_data = {
 	.gpio_pwdown		= GPIO_E7XX_IR_OFF,
 	.transceiver_cap	= IR_SIRMODE | IR_OFF,
@@ -165,6 +174,7 @@ static struct platform_device e330_tc6387xb_device = {
 
 static struct platform_device *e330_devices[] __initdata = {
 	&e330_tc6387xb_device,
+	&e7xx_gpio_vbus,
 };
 
 static void __init e330_init(void)
@@ -175,7 +185,6 @@ static void __init e330_init(void)
 	eseries_register_clks();
 	eseries_get_tmio_gpios();
 	platform_add_devices(ARRAY_AND_SIZE(e330_devices));
-	pxa_set_udc_info(&e7xx_udc_mach_info);
 }
 
 MACHINE_START(E330, "Toshiba e330")
@@ -214,6 +223,7 @@ static struct platform_device e350_t7l66xb_device = {
 
 static struct platform_device *e350_devices[] __initdata = {
 	&e350_t7l66xb_device,
+	&e7xx_gpio_vbus,
 };
 
 static void __init e350_init(void)
@@ -224,7 +234,6 @@ static void __init e350_init(void)
 	eseries_register_clks();
 	eseries_get_tmio_gpios();
 	platform_add_devices(ARRAY_AND_SIZE(e350_devices));
-	pxa_set_udc_info(&e7xx_udc_mach_info);
 }
 
 MACHINE_START(E350, "Toshiba e350")
@@ -333,6 +342,7 @@ static struct platform_device e400_t7l66xb_device = {
 
 static struct platform_device *e400_devices[] __initdata = {
 	&e400_t7l66xb_device,
+	&e7xx_gpio_vbus,
 };
 
 static void __init e400_init(void)
@@ -344,9 +354,8 @@ static void __init e400_init(void)
 	/* Fixme - e400 may have a switched clock */
 	eseries_register_clks();
 	eseries_get_tmio_gpios();
-	set_pxa_fb_info(&e400_pxafb_mach_info);
+	pxa_set_fb_info(NULL, &e400_pxafb_mach_info);
 	platform_add_devices(ARRAY_AND_SIZE(e400_devices));
-	pxa_set_udc_info(&e7xx_udc_mach_info);
 }
 
 MACHINE_START(E400, "Toshiba e400")
@@ -519,6 +528,7 @@ static struct platform_device e740_t7l66xb_device = {
 static struct platform_device *e740_devices[] __initdata = {
 	&e740_fb_device,
 	&e740_t7l66xb_device,
+	&e7xx_gpio_vbus,
 };
 
 static void __init e740_init(void)
@@ -532,7 +542,6 @@ static void __init e740_init(void)
 			"UDCCLK", &pxa25x_device_udc.dev),
 	eseries_get_tmio_gpios();
 	platform_add_devices(ARRAY_AND_SIZE(e740_devices));
-	pxa_set_udc_info(&e7xx_udc_mach_info);
 	pxa_set_ac97_info(NULL);
 	pxa_set_ficp_info(&e7xx_ficp_platform_data);
 }
@@ -711,6 +720,7 @@ static struct platform_device e750_tc6393xb_device = {
 static struct platform_device *e750_devices[] __initdata = {
 	&e750_fb_device,
 	&e750_tc6393xb_device,
+	&e7xx_gpio_vbus,
 };
 
 static void __init e750_init(void)
@@ -723,7 +733,6 @@ static void __init e750_init(void)
 			"GPIO11_CLK", NULL),
 	eseries_get_tmio_gpios();
 	platform_add_devices(ARRAY_AND_SIZE(e750_devices));
-	pxa_set_udc_info(&e7xx_udc_mach_info);
 	pxa_set_ac97_info(NULL);
 	pxa_set_ficp_info(&e7xx_ficp_platform_data);
 }
@@ -873,12 +882,21 @@ static struct platform_device e800_fb_device = {
 
 /* --------------------------- UDC definitions --------------------------- */
 
-static struct pxa2xx_udc_mach_info e800_udc_mach_info = {
+static struct gpio_vbus_mach_info e800_udc_info = {
 	.gpio_vbus   = GPIO_E800_USB_DISC,
 	.gpio_pullup = GPIO_E800_USB_PULLUP,
 	.gpio_pullup_inverted = 1
 };
 
+static struct platform_device e800_gpio_vbus = {
+	.name	= "gpio-vbus",
+	.id	= -1,
+	.dev	= {
+		.platform_data	= &e800_udc_info,
+	},
+};
+
+
 /* ----------------- e800 tc6393xb parameters ------------------ */
 
 static struct tc6393xb_platform_data e800_tc6393xb_info = {
@@ -907,6 +925,7 @@ static struct platform_device e800_tc6393xb_device = {
 static struct platform_device *e800_devices[] __initdata = {
 	&e800_fb_device,
 	&e800_tc6393xb_device,
+	&e800_gpio_vbus,
 };
 
 static void __init e800_init(void)
@@ -919,7 +938,6 @@ static void __init e800_init(void)
 			"GPIO11_CLK", NULL),
 	eseries_get_tmio_gpios();
 	platform_add_devices(ARRAY_AND_SIZE(e800_devices));
-	pxa_set_udc_info(&e800_udc_mach_info);
 	pxa_set_ac97_info(NULL);
 }
 

+ 6 - 6
arch/arm/mach-pxa/ezx.c

@@ -783,7 +783,7 @@ static void __init a780_init(void)
 
 	pxa_set_i2c_info(NULL);
 
-	set_pxa_fb_info(&ezx_fb_info_1);
+	pxa_set_fb_info(NULL, &ezx_fb_info_1);
 
 	pxa_set_keypad_info(&a780_keypad_platform_data);
 
@@ -853,7 +853,7 @@ static void __init e680_init(void)
 	pxa_set_i2c_info(NULL);
 	i2c_register_board_info(0, ARRAY_AND_SIZE(e680_i2c_board_info));
 
-	set_pxa_fb_info(&ezx_fb_info_1);
+	pxa_set_fb_info(NULL, &ezx_fb_info_1);
 
 	pxa_set_keypad_info(&e680_keypad_platform_data);
 
@@ -918,7 +918,7 @@ static void __init a1200_init(void)
 	pxa_set_i2c_info(NULL);
 	i2c_register_board_info(0, ARRAY_AND_SIZE(a1200_i2c_board_info));
 
-	set_pxa_fb_info(&ezx_fb_info_2);
+	pxa_set_fb_info(NULL, &ezx_fb_info_2);
 
 	pxa_set_keypad_info(&a1200_keypad_platform_data);
 
@@ -1103,7 +1103,7 @@ static void __init a910_init(void)
 	pxa_set_i2c_info(NULL);
 	i2c_register_board_info(0, ARRAY_AND_SIZE(a910_i2c_board_info));
 
-	set_pxa_fb_info(&ezx_fb_info_2);
+	pxa_set_fb_info(NULL, &ezx_fb_info_2);
 
 	pxa_set_keypad_info(&a910_keypad_platform_data);
 
@@ -1173,7 +1173,7 @@ static void __init e6_init(void)
 	pxa_set_i2c_info(NULL);
 	i2c_register_board_info(0, ARRAY_AND_SIZE(e6_i2c_board_info));
 
-	set_pxa_fb_info(&ezx_fb_info_2);
+	pxa_set_fb_info(NULL, &ezx_fb_info_2);
 
 	pxa_set_keypad_info(&e6_keypad_platform_data);
 
@@ -1212,7 +1212,7 @@ static void __init e2_init(void)
 	pxa_set_i2c_info(NULL);
 	i2c_register_board_info(0, ARRAY_AND_SIZE(e2_i2c_board_info));
 
-	set_pxa_fb_info(&ezx_fb_info_2);
+	pxa_set_fb_info(NULL, &ezx_fb_info_2);
 
 	pxa_set_keypad_info(&e2_keypad_platform_data);
 

+ 11 - 2
arch/arm/mach-pxa/gumstix.c

@@ -26,6 +26,7 @@
 #include <linux/gpio.h>
 #include <linux/err.h>
 #include <linux/clk.h>
+#include <linux/usb/gpio_vbus.h>
 
 #include <asm/setup.h>
 #include <asm/memory.h>
@@ -106,14 +107,22 @@ static void __init gumstix_mmc_init(void)
 #endif
 
 #ifdef CONFIG_USB_GADGET_PXA25X
-static struct pxa2xx_udc_mach_info gumstix_udc_info __initdata = {
+static struct gpio_vbus_mach_info gumstix_udc_info = {
 	.gpio_vbus		= GPIO_GUMSTIX_USB_GPIOn,
 	.gpio_pullup		= GPIO_GUMSTIX_USB_GPIOx,
 };
 
+static struct platform_device gumstix_gpio_vbus = {
+	.name	= "gpio-vbus",
+	.id	= -1,
+	.dev	= {
+		.platform_data	= &gumstix_udc_info,
+	},
+};
+
 static void __init gumstix_udc_init(void)
 {
-	pxa_set_udc_info(&gumstix_udc_info);
+	platform_device_register(&gumstix_gpio_vbus);
 }
 #else
 static void gumstix_udc_init(void)

+ 1 - 1
arch/arm/mach-pxa/idp.c

@@ -167,7 +167,7 @@ static void __init idp_init(void)
 
 	platform_device_register(&smc91x_device);
 	//platform_device_register(&mst_audio_device);
-	set_pxa_fb_info(&sharp_lm8v31);
+	pxa_set_fb_info(NULL, &sharp_lm8v31);
 	pxa_set_mci_info(&idp_mci_platform_data);
 }
 

+ 5 - 0
arch/arm/mach-pxa/include/mach/palmz72.h

@@ -44,6 +44,11 @@
 #define GPIO_NR_PALMZ72_BT_POWER		17
 #define GPIO_NR_PALMZ72_BT_RESET		83
 
+/* Camera */
+#define GPIO_NR_PALMZ72_CAM_PWDN		56
+#define GPIO_NR_PALMZ72_CAM_RESET		57
+#define GPIO_NR_PALMZ72_CAM_POWER		91
+
 /** Initial values **/
 
 /* Battery */

+ 2 - 2
arch/arm/mach-pxa/include/mach/pxafb.h

@@ -154,8 +154,8 @@ struct pxafb_mach_info {
 	void (*pxafb_lcd_power)(int, struct fb_var_screeninfo *);
 	void (*smart_update)(struct fb_info *);
 };
-void set_pxa_fb_info(struct pxafb_mach_info *hard_pxa_fb_info);
-void set_pxa_fb_parent(struct device *parent_dev);
+
+void pxa_set_fb_info(struct device *, struct pxafb_mach_info *);
 unsigned long pxafb_get_hsync_time(struct device *dev);
 
 extern int pxafb_smart_queue(struct fb_info *info, uint16_t *cmds, int);

+ 1 - 2
arch/arm/mach-pxa/include/mach/z2.h

@@ -25,8 +25,7 @@
 #define	GPIO98_ZIPITZ2_LID_BUTTON	98
 
 /* Libertas GSPI8686 WiFi */
-#define	GPIO14_ZIPITZ2_WIFI_RESET	14
-#define	GPIO15_ZIPITZ2_WIFI_POWER	15
+#define	GPIO14_ZIPITZ2_WIFI_POWER	14
 #define	GPIO24_ZIPITZ2_WIFI_CS		24
 #define	GPIO36_ZIPITZ2_WIFI_IRQ		36
 

+ 1 - 1
arch/arm/mach-pxa/littleton.c

@@ -185,7 +185,7 @@ static struct pxafb_mach_info littleton_lcd_info = {
 
 static void littleton_init_lcd(void)
 {
-	set_pxa_fb_info(&littleton_lcd_info);
+	pxa_set_fb_info(NULL, &littleton_lcd_info);
 }
 #else
 static inline void littleton_init_lcd(void) {};

+ 1 - 1
arch/arm/mach-pxa/lpd270.c

@@ -480,7 +480,7 @@ static void __init lpd270_init(void)
 	pxa_set_ac97_info(NULL);
 
 	if (lpd270_lcd_to_use != NULL)
-		set_pxa_fb_info(lpd270_lcd_to_use);
+		pxa_set_fb_info(NULL, lpd270_lcd_to_use);
 
 	pxa_set_ohci_info(&lpd270_ohci_platform_data);
 }

+ 1 - 1
arch/arm/mach-pxa/lubbock.c

@@ -521,7 +521,7 @@ static void __init lubbock_init(void)
 
 	clk_add_alias("SA1111_CLK", NULL, "GPIO11_CLK", NULL);
 	pxa_set_udc_info(&udc_info);
-	set_pxa_fb_info(&sharp_lm8v31);
+	pxa_set_fb_info(NULL, &sharp_lm8v31);
 	pxa_set_mci_info(&lubbock_mci_platform_data);
 	pxa_set_ficp_info(&lubbock_ficp_platform_data);
 	pxa_set_ac97_info(NULL);

+ 1 - 1
arch/arm/mach-pxa/magician.c

@@ -757,7 +757,7 @@ static void __init magician_init(void)
 		gpio_direction_output(GPIO104_MAGICIAN_LCD_POWER_1, 0);
 		gpio_direction_output(GPIO105_MAGICIAN_LCD_POWER_2, 0);
 		gpio_direction_output(GPIO106_MAGICIAN_LCD_POWER_3, 0);
-		set_pxa_fb_info(lcd_select ? &samsung_info : &toppoly_info);
+		pxa_set_fb_info(NULL, lcd_select ? &samsung_info : &toppoly_info);
 	} else
 		pr_err("LCD detection: CPLD mapping failed\n");
 }

+ 1 - 1
arch/arm/mach-pxa/mainstone.c

@@ -592,7 +592,7 @@ static void __init mainstone_init(void)
 	else
 		mainstone_pxafb_info.modes = &toshiba_ltm035a776c_mode;
 
-	set_pxa_fb_info(&mainstone_pxafb_info);
+	pxa_set_fb_info(NULL, &mainstone_pxafb_info);
 	mainstone_backlight_register();
 
 	pxa_set_mci_info(&mainstone_mci_platform_data);

+ 1 - 1
arch/arm/mach-pxa/mioa701.c

@@ -795,7 +795,7 @@ static void __init mioa701_machine_init(void)
 	pxa_set_stuart_info(NULL);
 	mio_gpio_request(ARRAY_AND_SIZE(global_gpios));
 	bootstrap_init();
-	set_pxa_fb_info(&mioa701_pxafb_info);
+	pxa_set_fb_info(NULL, &mioa701_pxafb_info);
 	pxa_set_mci_info(&mioa701_mci_info);
 	pxa_set_keypad_info(&mioa701_keypad_info);
 	pxa_set_udc_info(&mioa701_udc_info);

+ 2 - 3
arch/arm/mach-pxa/palm27x.c

@@ -1,8 +1,7 @@
 /*
  * Common code for Palm LD, T5, TX, Z72
  *
- * Copyright (C) 2010
- * Marek Vasut <marek.vasut@gmail.com>
+ * Copyright (C) 2010-2011 Marek Vasut <marek.vasut@gmail.com>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
@@ -158,7 +157,7 @@ void __init palm27x_lcd_init(int power, struct pxafb_mode_info *mode)
 		palm27x_lcd_screen.pxafb_lcd_power = palm27x_lcd_ctl;
 	}
 
-	set_pxa_fb_info(&palm27x_lcd_screen);
+	pxa_set_fb_info(NULL, &palm27x_lcd_screen);
 }
 #endif
 

+ 1 - 1
arch/arm/mach-pxa/palmtc.c

@@ -507,7 +507,7 @@ static struct pxafb_mach_info palmtc_lcd_screen = {
 
 static void __init palmtc_lcd_init(void)
 {
-	set_pxa_fb_info(&palmtc_lcd_screen);
+	pxa_set_fb_info(NULL, &palmtc_lcd_screen);
 }
 #else
 static inline void palmtc_lcd_init(void) {}

+ 8 - 25
arch/arm/mach-pxa/palmte2.c

@@ -136,30 +136,14 @@ static struct platform_device palmte2_pxa_keys = {
 /******************************************************************************
  * Backlight
  ******************************************************************************/
+static struct gpio palmte_bl_gpios[] = {
+	{ GPIO_NR_PALMTE2_BL_POWER, GPIOF_INIT_LOW, "Backlight power" },
+	{ GPIO_NR_PALMTE2_LCD_POWER, GPIOF_INIT_LOW, "LCD power" },
+};
+
 static int palmte2_backlight_init(struct device *dev)
 {
-	int ret;
-
-	ret = gpio_request(GPIO_NR_PALMTE2_BL_POWER, "BL POWER");
-	if (ret)
-		goto err;
-	ret = gpio_direction_output(GPIO_NR_PALMTE2_BL_POWER, 0);
-	if (ret)
-		goto err2;
-	ret = gpio_request(GPIO_NR_PALMTE2_LCD_POWER, "LCD POWER");
-	if (ret)
-		goto err2;
-	ret = gpio_direction_output(GPIO_NR_PALMTE2_LCD_POWER, 0);
-	if (ret)
-		goto err3;
-
-	return 0;
-err3:
-	gpio_free(GPIO_NR_PALMTE2_LCD_POWER);
-err2:
-	gpio_free(GPIO_NR_PALMTE2_BL_POWER);
-err:
-	return ret;
+	return gpio_request_array(ARRAY_AND_SIZE(palmte_bl_gpios));
 }
 
 static int palmte2_backlight_notify(struct device *dev, int brightness)
@@ -171,8 +155,7 @@ static int palmte2_backlight_notify(struct device *dev, int brightness)
 
 static void palmte2_backlight_exit(struct device *dev)
 {
-	gpio_free(GPIO_NR_PALMTE2_BL_POWER);
-	gpio_free(GPIO_NR_PALMTE2_LCD_POWER);
+	gpio_free_array(ARRAY_AND_SIZE(palmte_bl_gpios));
 }
 
 static struct platform_pwm_backlight_data palmte2_backlight_data = {
@@ -363,7 +346,7 @@ static void __init palmte2_init(void)
 	pxa_set_btuart_info(NULL);
 	pxa_set_stuart_info(NULL);
 
-	set_pxa_fb_info(&palmte2_lcd_screen);
+	pxa_set_fb_info(NULL, &palmte2_lcd_screen);
 	pxa_set_mci_info(&palmte2_mci_platform_data);
 	palmte2_udc_init();
 	pxa_set_ac97_info(&palmte2_ac97_pdata);

+ 127 - 0
arch/arm/mach-pxa/palmz72.c

@@ -30,6 +30,7 @@
 #include <linux/wm97xx.h>
 #include <linux/power_supply.h>
 #include <linux/usb/gpio_vbus.h>
+#include <linux/i2c-gpio.h>
 
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
@@ -47,6 +48,9 @@
 #include <mach/palm27x.h>
 
 #include <mach/pm.h>
+#include <mach/camera.h>
+
+#include <media/soc_camera.h>
 
 #include "generic.h"
 #include "devices.h"
@@ -103,6 +107,28 @@ static unsigned long palmz72_pin_config[] __initdata = {
 	GPIO22_GPIO,	/* LCD border color */
 	GPIO96_GPIO,	/* lcd power */
 
+	/* PXA Camera */
+	GPIO81_CIF_DD_0,
+	GPIO48_CIF_DD_5,
+	GPIO50_CIF_DD_3,
+	GPIO51_CIF_DD_2,
+	GPIO52_CIF_DD_4,
+	GPIO53_CIF_MCLK,
+	GPIO54_CIF_PCLK,
+	GPIO55_CIF_DD_1,
+	GPIO84_CIF_FV,
+	GPIO85_CIF_LV,
+	GPIO93_CIF_DD_6,
+	GPIO108_CIF_DD_7,
+
+	GPIO56_GPIO,	/* OV9640 Powerdown */
+	GPIO57_GPIO,	/* OV9640 Reset */
+	GPIO91_GPIO,	/* OV9640 Power */
+
+	/* I2C */
+	GPIO117_GPIO,	/* I2C_SCL */
+	GPIO118_GPIO,	/* I2C_SDA */
+
 	/* Misc. */
 	GPIO0_GPIO	| WAKEUP_ON_LEVEL_HIGH,	/* power detect */
 	GPIO88_GPIO,				/* green led */
@@ -253,6 +279,106 @@ static int __init palmz72_pm_init(void)
 device_initcall(palmz72_pm_init);
 #endif
 
+/******************************************************************************
+ * SoC Camera
+ ******************************************************************************/
+#if defined(CONFIG_SOC_CAMERA_OV9640) || \
+	defined(CONFIG_SOC_CAMERA_OV9640_MODULE)
+static struct pxacamera_platform_data palmz72_pxacamera_platform_data = {
+	.flags		= PXA_CAMERA_MASTER | PXA_CAMERA_DATAWIDTH_8 |
+			PXA_CAMERA_PCLK_EN | PXA_CAMERA_MCLK_EN,
+	.mclk_10khz	= 2600,
+};
+
+/* Board I2C devices. */
+static struct i2c_board_info palmz72_i2c_device[] = {
+	{
+		I2C_BOARD_INFO("ov9640", 0x30),
+	}
+};
+
+static int palmz72_camera_power(struct device *dev, int power)
+{
+	gpio_set_value(GPIO_NR_PALMZ72_CAM_PWDN, !power);
+	mdelay(50);
+	return 0;
+}
+
+static int palmz72_camera_reset(struct device *dev)
+{
+	gpio_set_value(GPIO_NR_PALMZ72_CAM_RESET, 1);
+	mdelay(50);
+	gpio_set_value(GPIO_NR_PALMZ72_CAM_RESET, 0);
+	mdelay(50);
+	return 0;
+}
+
+static struct soc_camera_link palmz72_iclink = {
+	.bus_id		= 0, /* Match id in pxa27x_device_camera in device.c */
+	.board_info	= &palmz72_i2c_device[0],
+	.i2c_adapter_id	= 0,
+	.module_name	= "ov96xx",
+	.power		= &palmz72_camera_power,
+	.reset		= &palmz72_camera_reset,
+	.flags		= SOCAM_DATAWIDTH_8,
+};
+
+static struct i2c_gpio_platform_data palmz72_i2c_bus_data = {
+	.sda_pin	= 118,
+	.scl_pin	= 117,
+	.udelay		= 10,
+	.timeout	= 100,
+};
+
+static struct platform_device palmz72_i2c_bus_device = {
+	.name		= "i2c-gpio",
+	.id		= 0, /* we use this as a replacement for i2c-pxa */
+	.dev		= {
+		.platform_data	= &palmz72_i2c_bus_data,
+	}
+};
+
+static struct platform_device palmz72_camera = {
+	.name	= "soc-camera-pdrv",
+	.id	= -1,
+	.dev	= {
+		.platform_data	= &palmz72_iclink,
+	},
+};
+
+/* Here we request the camera GPIOs and configure them. We power up the camera
+ * module, deassert the reset pin, but put it into powerdown (low to no power
+ * consumption) mode. This allows us to later bring the module up fast. */
+static struct gpio palmz72_camera_gpios[] = {
+	{ GPIO_NR_PALMZ72_CAM_POWER,	GPIOF_INIT_HIGH,"Camera DVDD" },
+	{ GPIO_NR_PALMZ72_CAM_RESET,	GPIOF_INIT_LOW,	"Camera RESET" },
+	{ GPIO_NR_PALMZ72_CAM_PWDN,	GPIOF_INIT_LOW,	"Camera PWDN" },
+};
+
+static inline void __init palmz72_cam_gpio_init(void)
+{
+	int ret;
+
+	ret = gpio_request_array(ARRAY_AND_SIZE(palmz72_camera_gpios));
+	if (!ret)
+		gpio_free_array(ARRAY_AND_SIZE(palmz72_camera_gpios));
+	else
+		printk(KERN_ERR "Camera GPIO init failed!\n");
+
+	return;
+}
+
+static void __init palmz72_camera_init(void)
+{
+	palmz72_cam_gpio_init();
+	pxa_set_camera_info(&palmz72_pxacamera_platform_data);
+	platform_device_register(&palmz72_i2c_bus_device);
+	platform_device_register(&palmz72_camera);
+}
+#else
+static inline void palmz72_camera_init(void) {}
+#endif
+
 /******************************************************************************
  * Machine init
  ******************************************************************************/
@@ -276,6 +402,7 @@ static void __init palmz72_init(void)
 	palm27x_pmic_init();
 	palmz72_kpc_init();
 	palmz72_leds_init();
+	palmz72_camera_init();
 }
 
 MACHINE_START(PALMZ72, "Palm Zire72")

+ 1 - 1
arch/arm/mach-pxa/pcm990-baseboard.c

@@ -515,7 +515,7 @@ void __init pcm990_baseboard_init(void)
 	pcm990_init_irq();
 
 #ifndef CONFIG_PCM990_DISPLAY_NONE
-	set_pxa_fb_info(&pcm990_fbinfo);
+	pxa_set_fb_info(NULL, &pcm990_fbinfo);
 #endif
 	platform_device_register(&pcm990_backlight_device);
 

+ 1 - 2
arch/arm/mach-pxa/poodle.c

@@ -445,8 +445,7 @@ static void __init poodle_init(void)
 	if (ret)
 		pr_warning("poodle: Unable to register LoCoMo device\n");
 
-	set_pxa_fb_parent(&poodle_locomo_device.dev);
-	set_pxa_fb_info(&poodle_fb_info);
+	pxa_set_fb_info(&poodle_locomo_device.dev, &poodle_fb_info);
 	pxa_set_udc_info(&udc_info);
 	pxa_set_mci_info(&poodle_mci_platform_data);
 	pxa_set_ficp_info(&poodle_ficp_platform_data);

+ 1 - 1
arch/arm/mach-pxa/raumfeld.c

@@ -597,7 +597,7 @@ static void __init raumfeld_lcd_init(void)
 {
 	int ret;
 
-	set_pxa_fb_info(&raumfeld_sharp_lcd_info);
+	pxa_set_fb_info(NULL, &raumfeld_sharp_lcd_info);
 
 	/* Earlier devices had the backlight regulator controlled
 	 * via PWM, later versions use another controller for that */

+ 1 - 1
arch/arm/mach-pxa/saar.c

@@ -473,7 +473,7 @@ static struct pxafb_mach_info saar_lcd_info = {
 
 static void __init saar_init_lcd(void)
 {
-	set_pxa_fb_info(&saar_lcd_info);
+	pxa_set_fb_info(NULL, &saar_lcd_info);
 }
 #else
 static inline void saar_init_lcd(void) {}

+ 1 - 1
arch/arm/mach-pxa/spitz.c

@@ -724,7 +724,7 @@ static struct pxafb_mach_info spitz_pxafb_info = {
 
 static void __init spitz_lcd_init(void)
 {
-	set_pxa_fb_info(&spitz_pxafb_info);
+	pxa_set_fb_info(NULL, &spitz_pxafb_info);
 }
 #else
 static inline void spitz_lcd_init(void) {}

+ 1 - 1
arch/arm/mach-pxa/tavorevb.c

@@ -466,7 +466,7 @@ static void __init tavorevb_init_lcd(void)
 {
 	platform_device_register(&tavorevb_backlight_devices[0]);
 	platform_device_register(&tavorevb_backlight_devices[1]);
-	set_pxa_fb_info(&tavorevb_lcd_info);
+	pxa_set_fb_info(NULL, &tavorevb_lcd_info);
 }
 #else
 static inline void tavorevb_init_lcd(void) {}

+ 2 - 3
arch/arm/mach-pxa/time.c

@@ -100,7 +100,6 @@ pxa_osmr0_set_mode(enum clock_event_mode mode, struct clock_event_device *dev)
 static struct clock_event_device ckevt_pxa_osmr0 = {
 	.name		= "osmr0",
 	.features	= CLOCK_EVT_FEAT_ONESHOT,
-	.shift		= 32,
 	.rating		= 200,
 	.set_next_event	= pxa_osmr0_set_next_event,
 	.set_mode	= pxa_osmr0_set_mode,
@@ -135,8 +134,8 @@ static void __init pxa_timer_init(void)
 
 	init_sched_clock(&cd, pxa_update_sched_clock, 32, clock_tick_rate);
 
-	ckevt_pxa_osmr0.mult =
-		div_sc(clock_tick_rate, NSEC_PER_SEC, ckevt_pxa_osmr0.shift);
+	clocksource_calc_mult_shift(&cksrc_pxa_oscr0, clock_tick_rate, 4);
+	clockevents_calc_mult_shift(&ckevt_pxa_osmr0, clock_tick_rate, 4);
 	ckevt_pxa_osmr0.max_delta_ns =
 		clockevent_delta2ns(0x7fffffff, &ckevt_pxa_osmr0);
 	ckevt_pxa_osmr0.min_delta_ns =

+ 11 - 2
arch/arm/mach-pxa/tosa.c

@@ -35,6 +35,7 @@
 #include <linux/spi/pxa2xx_spi.h>
 #include <linux/input/matrix_keypad.h>
 #include <linux/i2c/pxa-i2c.h>
+#include <linux/usb/gpio_vbus.h>
 
 #include <asm/setup.h>
 #include <asm/mach-types.h>
@@ -240,12 +241,20 @@ static struct scoop_pcmcia_config tosa_pcmcia_config = {
 /*
  * USB Device Controller
  */
-static struct pxa2xx_udc_mach_info udc_info __initdata = {
+static struct gpio_vbus_mach_info tosa_udc_info = {
 	.gpio_pullup		= TOSA_GPIO_USB_PULLUP,
 	.gpio_vbus		= TOSA_GPIO_USB_IN,
 	.gpio_vbus_inverted	= 1,
 };
 
+static struct platform_device tosa_gpio_vbus = {
+	.name	= "gpio-vbus",
+	.id	= -1,
+	.dev	= {
+		.platform_data	= &tosa_udc_info,
+	},
+};
+
 /*
  * MMC/SD Device
  */
@@ -891,6 +900,7 @@ static struct platform_device *devices[] __initdata = {
 	&tosa_bt_device,
 	&sharpsl_rom_device,
 	&wm9712_device,
+	&tosa_gpio_vbus,
 };
 
 static void tosa_poweroff(void)
@@ -937,7 +947,6 @@ static void __init tosa_init(void)
 	dummy = gpiochip_reserve(TOSA_TC6393XB_GPIO_BASE, 16);
 
 	pxa_set_mci_info(&tosa_mci_platform_data);
-	pxa_set_udc_info(&udc_info);
 	pxa_set_ficp_info(&tosa_ficp_platform_data);
 	pxa_set_i2c_info(NULL);
 	pxa_set_ac97_info(NULL);

+ 2 - 2
arch/arm/mach-pxa/trizeps4.c

@@ -516,9 +516,9 @@ static void __init trizeps4_init(void)
 	pxa_set_stuart_info(NULL);
 
 	if (0)	/* dont know how to determine LCD */
-		set_pxa_fb_info(&sharp_lcd);
+		pxa_set_fb_info(NULL, &sharp_lcd);
 	else
-		set_pxa_fb_info(&toshiba_lcd);
+		pxa_set_fb_info(NULL, &toshiba_lcd);
 
 	pxa_set_mci_info(&trizeps4_mci_platform_data);
 #ifndef STATUS_LEDS_ON_STUART_PINS

+ 1 - 1
arch/arm/mach-pxa/viper.c

@@ -932,7 +932,7 @@ static void __init viper_init(void)
 	/* Wake-up serial console */
 	viper_init_serial_gpio();
 
-	set_pxa_fb_info(&fb_info);
+	pxa_set_fb_info(NULL, &fb_info);
 
 	/* v1 hardware cannot use the datacs line */
 	version = viper_hw_version();

+ 1 - 1
arch/arm/mach-pxa/vpac270.c

@@ -572,7 +572,7 @@ static void __init vpac270_lcd_init(void)
 	}
 
 	vpac270_lcd_screen.pxafb_lcd_power = vpac270_lcd_power;
-	set_pxa_fb_info(&vpac270_lcd_screen);
+	pxa_set_fb_info(NULL, &vpac270_lcd_screen);
 	return;
 
 err2:

+ 38 - 39
arch/arm/mach-pxa/z2.c

@@ -91,13 +91,13 @@ static unsigned long z2_pin_config[] = {
 	GPIO47_STUART_TXD,
 
 	/* Keypad */
-	GPIO100_KP_MKIN_0	| WAKEUP_ON_LEVEL_HIGH,
-	GPIO101_KP_MKIN_1	| WAKEUP_ON_LEVEL_HIGH,
-	GPIO102_KP_MKIN_2	| WAKEUP_ON_LEVEL_HIGH,
-	GPIO34_KP_MKIN_3	| WAKEUP_ON_LEVEL_HIGH,
-	GPIO38_KP_MKIN_4	| WAKEUP_ON_LEVEL_HIGH,
-	GPIO16_KP_MKIN_5	| WAKEUP_ON_LEVEL_HIGH,
-	GPIO17_KP_MKIN_6	| WAKEUP_ON_LEVEL_HIGH,
+	GPIO100_KP_MKIN_0,
+	GPIO101_KP_MKIN_1,
+	GPIO102_KP_MKIN_2,
+	GPIO34_KP_MKIN_3,
+	GPIO38_KP_MKIN_4,
+	GPIO16_KP_MKIN_5,
+	GPIO17_KP_MKIN_6,
 	GPIO103_KP_MKOUT_0,
 	GPIO104_KP_MKOUT_1,
 	GPIO105_KP_MKOUT_2,
@@ -138,8 +138,7 @@ static unsigned long z2_pin_config[] = {
 	GPIO1_GPIO,		/* Power button */
 	GPIO37_GPIO,		/* Headphone detect */
 	GPIO98_GPIO,		/* Lid switch */
-	GPIO14_GPIO,		/* WiFi Reset */
-	GPIO15_GPIO,		/* WiFi Power */
+	GPIO14_GPIO,		/* WiFi Power */
 	GPIO24_GPIO,		/* WiFi CS */
 	GPIO36_GPIO,		/* WiFi IRQ */
 	GPIO88_GPIO,		/* LCD CS */
@@ -204,7 +203,7 @@ static struct platform_pwm_backlight_data z2_backlight_data[] = {
 		/* Keypad Backlight */
 		.pwm_id		= 1,
 		.max_brightness	= 1023,
-		.dft_brightness	= 512,
+		.dft_brightness	= 0,
 		.pwm_period_ns	= 1260320,
 	},
 	[1] = {
@@ -271,7 +270,7 @@ static struct pxafb_mach_info z2_lcd_screen = {
 
 static void __init z2_lcd_init(void)
 {
-	set_pxa_fb_info(&z2_lcd_screen);
+	pxa_set_fb_info(NULL, &z2_lcd_screen);
 }
 #else
 static inline void z2_lcd_init(void) {}
@@ -309,12 +308,12 @@ struct gpio_led z2_gpio_leds[] = {
 	.active_low		= 1,
 }, {
 	.name			= "z2:green:charged",
-	.default_trigger	= "none",
+	.default_trigger	= "mmc0",
 	.gpio			= GPIO85_ZIPITZ2_LED_CHARGED,
 	.active_low		= 1,
 }, {
 	.name			= "z2:amber:charging",
-	.default_trigger	= "none",
+	.default_trigger	= "Z2-charging-or-full",
 	.gpio			= GPIO83_ZIPITZ2_LED_CHARGING,
 	.active_low		= 1,
 },
@@ -427,8 +426,22 @@ static inline void z2_mkp_init(void) {}
  ******************************************************************************/
 #if defined(CONFIG_KEYBOARD_GPIO) || defined(CONFIG_KEYBOARD_GPIO_MODULE)
 static struct gpio_keys_button z2_pxa_buttons[] = {
-	{KEY_POWER, GPIO1_ZIPITZ2_POWER_BUTTON, 0, "Power Button" },
-	{KEY_CLOSE, GPIO98_ZIPITZ2_LID_BUTTON, 0, "Lid Button" },
+	{
+		.code		= KEY_POWER,
+		.gpio		= GPIO1_ZIPITZ2_POWER_BUTTON,
+		.active_low	= 0,
+		.desc		= "Power Button",
+		.wakeup		= 1,
+		.type		= EV_KEY,
+	},
+	{
+		.code		= SW_LID,
+		.gpio		= GPIO98_ZIPITZ2_LID_BUTTON,
+		.active_low	= 1,
+		.desc		= "Lid Switch",
+		.wakeup		= 0,
+		.type		= EV_SW,
+	},
 };
 
 static struct gpio_keys_platform_data z2_pxa_keys_data = {
@@ -461,9 +474,9 @@ static struct z2_battery_info batt_chip_info = {
 	.batt_I2C_addr	= 0x55,
 	.batt_I2C_reg	= 2,
 	.charge_gpio	= GPIO0_ZIPITZ2_AC_DETECT,
-	.min_voltage	= 2400000,
-	.max_voltage	= 3700000,
-	.batt_div	= 69,
+	.min_voltage	= 3475000,
+	.max_voltage	= 4190000,
+	.batt_div	= 59,
 	.batt_mult	= 1000000,
 	.batt_tech	= POWER_SUPPLY_TECHNOLOGY_LION,
 	.batt_name	= "Z2",
@@ -497,26 +510,16 @@ static int z2_lbs_spi_setup(struct spi_device *spi)
 {
 	int ret = 0;
 
-	ret = gpio_request(GPIO15_ZIPITZ2_WIFI_POWER, "WiFi Power");
+	ret = gpio_request(GPIO14_ZIPITZ2_WIFI_POWER, "WiFi Power");
 	if (ret)
 		goto err;
 
-	ret = gpio_direction_output(GPIO15_ZIPITZ2_WIFI_POWER, 1);
+	ret = gpio_direction_output(GPIO14_ZIPITZ2_WIFI_POWER, 1);
 	if (ret)
 		goto err2;
 
-	ret = gpio_request(GPIO14_ZIPITZ2_WIFI_RESET, "WiFi Reset");
-	if (ret)
-		goto err2;
-
-	ret = gpio_direction_output(GPIO14_ZIPITZ2_WIFI_RESET, 0);
-	if (ret)
-		goto err3;
-
-	/* Reset the card */
+	/* Wait until card is powered on */
 	mdelay(180);
-	gpio_set_value(GPIO14_ZIPITZ2_WIFI_RESET, 1);
-	mdelay(20);
 
 	spi->bits_per_word = 16;
 	spi->mode = SPI_MODE_2,
@@ -525,22 +528,18 @@ static int z2_lbs_spi_setup(struct spi_device *spi)
 
 	return 0;
 
-err3:
-	gpio_free(GPIO14_ZIPITZ2_WIFI_RESET);
 err2:
-	gpio_free(GPIO15_ZIPITZ2_WIFI_POWER);
+	gpio_free(GPIO14_ZIPITZ2_WIFI_POWER);
 err:
 	return ret;
 };
 
 static int z2_lbs_spi_teardown(struct spi_device *spi)
 {
-	gpio_set_value(GPIO14_ZIPITZ2_WIFI_RESET, 0);
-	gpio_set_value(GPIO15_ZIPITZ2_WIFI_POWER, 0);
-	gpio_free(GPIO14_ZIPITZ2_WIFI_RESET);
-	gpio_free(GPIO15_ZIPITZ2_WIFI_POWER);
-	return 0;
+	gpio_set_value(GPIO14_ZIPITZ2_WIFI_POWER, 0);
+	gpio_free(GPIO14_ZIPITZ2_WIFI_POWER);
 
+	return 0;
 };
 
 static struct pxa2xx_spi_chip z2_lbs_chip_info = {

+ 1 - 1
arch/arm/mach-pxa/zeus.c

@@ -846,7 +846,7 @@ static void __init zeus_init(void)
 	if (zeus_setup_fb_gpios())
 		pr_err("Failed to setup fb gpios\n");
 	else
-		set_pxa_fb_info(&zeus_fb_info);
+		pxa_set_fb_info(NULL, &zeus_fb_info);
 
 	pxa_set_mci_info(&zeus_mci_platform_data);
 	pxa_set_udc_info(&zeus_udc_info);

+ 2 - 2
arch/arm/mach-pxa/zylonite.c

@@ -208,7 +208,7 @@ static void __init zylonite_init_lcd(void)
 	platform_device_register(&zylonite_backlight_device);
 
 	if (lcd_id & 0x20) {
-		set_pxa_fb_info(&zylonite_sharp_lcd_info);
+		pxa_set_fb_info(NULL, &zylonite_sharp_lcd_info);
 		return;
 	}
 
@@ -220,7 +220,7 @@ static void __init zylonite_init_lcd(void)
 	else
 		zylonite_toshiba_lcd_info.modes = &toshiba_ltm04c380k_mode;
 
-	set_pxa_fb_info(&zylonite_toshiba_lcd_info);
+	pxa_set_fb_info(NULL, &zylonite_toshiba_lcd_info);
 }
 #else
 static inline void zylonite_init_lcd(void) {}

+ 22 - 21
drivers/ata/pata_palmld.c

@@ -33,6 +33,11 @@
 
 #define DRV_NAME "pata_palmld"
 
+static struct gpio palmld_hdd_gpios[] = {
+	{ GPIO_NR_PALMLD_IDE_PWEN,	GPIOF_INIT_HIGH,	"HDD Power" },
+	{ GPIO_NR_PALMLD_IDE_RESET,	GPIOF_INIT_LOW,		"HDD Reset" },
+};
+
 static struct scsi_host_template palmld_sht = {
 	ATA_PIO_SHT(DRV_NAME),
 };
@@ -52,28 +57,23 @@ static __devinit int palmld_pata_probe(struct platform_device *pdev)
 
 	/* allocate host */
 	host = ata_host_alloc(&pdev->dev, 1);
-	if (!host)
-		return -ENOMEM;
+	if (!host) {
+		ret = -ENOMEM;
+		goto err1;
+	}
 
 	/* remap drive's physical memory address */
 	mem = devm_ioremap(&pdev->dev, PALMLD_IDE_PHYS, 0x1000);
-	if (!mem)
-		return -ENOMEM;
+	if (!mem) {
+		ret = -ENOMEM;
+		goto err1;
+	}
 
 	/* request and activate power GPIO, IRQ GPIO */
-	ret = gpio_request(GPIO_NR_PALMLD_IDE_PWEN, "HDD PWR");
+	ret = gpio_request_array(palmld_hdd_gpios,
+				ARRAY_SIZE(palmld_hdd_gpios));
 	if (ret)
 		goto err1;
-	ret = gpio_direction_output(GPIO_NR_PALMLD_IDE_PWEN, 1);
-	if (ret)
-		goto err2;
-
-	ret = gpio_request(GPIO_NR_PALMLD_IDE_RESET, "HDD RST");
-	if (ret)
-		goto err2;
-	ret = gpio_direction_output(GPIO_NR_PALMLD_IDE_RESET, 0);
-	if (ret)
-		goto err3;
 
 	/* reset the drive */
 	gpio_set_value(GPIO_NR_PALMLD_IDE_RESET, 0);
@@ -96,13 +96,15 @@ static __devinit int palmld_pata_probe(struct platform_device *pdev)
 	ata_sff_std_ports(&ap->ioaddr);
 
 	/* activate host */
-	return ata_host_activate(host, 0, NULL, IRQF_TRIGGER_RISING,
+	ret = ata_host_activate(host, 0, NULL, IRQF_TRIGGER_RISING,
 					&palmld_sht);
+	if (ret)
+		goto err2;
+
+	return ret;
 
-err3:
-	gpio_free(GPIO_NR_PALMLD_IDE_RESET);
 err2:
-	gpio_free(GPIO_NR_PALMLD_IDE_PWEN);
+	gpio_free_array(palmld_hdd_gpios, ARRAY_SIZE(palmld_hdd_gpios));
 err1:
 	return ret;
 }
@@ -116,8 +118,7 @@ static __devexit int palmld_pata_remove(struct platform_device *dev)
 	/* power down the HDD */
 	gpio_set_value(GPIO_NR_PALMLD_IDE_PWEN, 0);
 
-	gpio_free(GPIO_NR_PALMLD_IDE_RESET);
-	gpio_free(GPIO_NR_PALMLD_IDE_PWEN);
+	gpio_free_array(palmld_hdd_gpios, ARRAY_SIZE(palmld_hdd_gpios));
 
 	return 0;
 }

+ 49 - 84
drivers/pcmcia/pxa2xx_colibri.c

@@ -34,14 +34,24 @@
 #define	COLIBRI320_DETECT_GPIO	81
 #define	COLIBRI320_READY_GPIO	29
 
-static struct {
-	int	reset_gpio;
-	int	ppen_gpio;
-	int	bvd1_gpio;
-	int	bvd2_gpio;
-	int	detect_gpio;
-	int	ready_gpio;
-} colibri_pcmcia_gpio;
+enum {
+	DETECT = 0,
+	READY = 1,
+	BVD1 = 2,
+	BVD2 = 3,
+	PPEN = 4,
+	RESET = 5,
+};
+
+/* Contents of this array are configured on-the-fly in init function */
+static struct gpio colibri_pcmcia_gpios[] = {
+	{ 0,	GPIOF_IN,	"PCMCIA Detect" },
+	{ 0,	GPIOF_IN,	"PCMCIA Ready" },
+	{ 0,	GPIOF_IN,	"PCMCIA BVD1" },
+	{ 0,	GPIOF_IN,	"PCMCIA BVD2" },
+	{ 0,	GPIOF_INIT_LOW,	"PCMCIA PPEN" },
+	{ 0,	GPIOF_INIT_HIGH,"PCMCIA Reset" },
+};
 
 static struct pcmcia_irqs colibri_irqs[] = {
 	{
@@ -54,88 +64,42 @@ static int colibri_pcmcia_hw_init(struct soc_pcmcia_socket *skt)
 {
 	int ret;
 
-	ret = gpio_request(colibri_pcmcia_gpio.detect_gpio, "DETECT");
+	ret = gpio_request_array(colibri_pcmcia_gpios,
+				ARRAY_SIZE(colibri_pcmcia_gpios));
 	if (ret)
 		goto err1;
-	ret = gpio_direction_input(colibri_pcmcia_gpio.detect_gpio);
-	if (ret)
-		goto err2;
-
-	ret = gpio_request(colibri_pcmcia_gpio.ready_gpio, "READY");
-	if (ret)
-		goto err2;
-	ret = gpio_direction_input(colibri_pcmcia_gpio.ready_gpio);
-	if (ret)
-		goto err3;
 
-	ret = gpio_request(colibri_pcmcia_gpio.bvd1_gpio, "BVD1");
-	if (ret)
-		goto err3;
-	ret = gpio_direction_input(colibri_pcmcia_gpio.bvd1_gpio);
-	if (ret)
-		goto err4;
+	colibri_irqs[0].irq = gpio_to_irq(colibri_pcmcia_gpios[DETECT].gpio);
+	skt->socket.pci_irq = gpio_to_irq(colibri_pcmcia_gpios[READY].gpio);
 
-	ret = gpio_request(colibri_pcmcia_gpio.bvd2_gpio, "BVD2");
-	if (ret)
-		goto err4;
-	ret = gpio_direction_input(colibri_pcmcia_gpio.bvd2_gpio);
-	if (ret)
-		goto err5;
-
-	ret = gpio_request(colibri_pcmcia_gpio.ppen_gpio, "PPEN");
-	if (ret)
-		goto err5;
-	ret = gpio_direction_output(colibri_pcmcia_gpio.ppen_gpio, 0);
-	if (ret)
-		goto err6;
-
-	ret = gpio_request(colibri_pcmcia_gpio.reset_gpio, "RESET");
-	if (ret)
-		goto err6;
-	ret = gpio_direction_output(colibri_pcmcia_gpio.reset_gpio, 1);
+	ret = soc_pcmcia_request_irqs(skt, colibri_irqs,
+					ARRAY_SIZE(colibri_irqs));
 	if (ret)
-		goto err7;
-
-	colibri_irqs[0].irq = gpio_to_irq(colibri_pcmcia_gpio.detect_gpio);
-	skt->socket.pci_irq = gpio_to_irq(colibri_pcmcia_gpio.ready_gpio);
+		goto err2;
 
-	return soc_pcmcia_request_irqs(skt, colibri_irqs,
-					ARRAY_SIZE(colibri_irqs));
+	return ret;
 
-err7:
-	gpio_free(colibri_pcmcia_gpio.detect_gpio);
-err6:
-	gpio_free(colibri_pcmcia_gpio.ready_gpio);
-err5:
-	gpio_free(colibri_pcmcia_gpio.bvd1_gpio);
-err4:
-	gpio_free(colibri_pcmcia_gpio.bvd2_gpio);
-err3:
-	gpio_free(colibri_pcmcia_gpio.reset_gpio);
 err2:
-	gpio_free(colibri_pcmcia_gpio.ppen_gpio);
+	gpio_free_array(colibri_pcmcia_gpios,
+			ARRAY_SIZE(colibri_pcmcia_gpios));
 err1:
 	return ret;
 }
 
 static void colibri_pcmcia_hw_shutdown(struct soc_pcmcia_socket *skt)
 {
-	gpio_free(colibri_pcmcia_gpio.detect_gpio);
-	gpio_free(colibri_pcmcia_gpio.ready_gpio);
-	gpio_free(colibri_pcmcia_gpio.bvd1_gpio);
-	gpio_free(colibri_pcmcia_gpio.bvd2_gpio);
-	gpio_free(colibri_pcmcia_gpio.reset_gpio);
-	gpio_free(colibri_pcmcia_gpio.ppen_gpio);
+	gpio_free_array(colibri_pcmcia_gpios,
+			ARRAY_SIZE(colibri_pcmcia_gpios));
 }
 
 static void colibri_pcmcia_socket_state(struct soc_pcmcia_socket *skt,
 					struct pcmcia_state *state)
 {
 
-	state->detect = !!gpio_get_value(colibri_pcmcia_gpio.detect_gpio);
-	state->ready  = !!gpio_get_value(colibri_pcmcia_gpio.ready_gpio);
-	state->bvd1   = !!gpio_get_value(colibri_pcmcia_gpio.bvd1_gpio);
-	state->bvd2   = !!gpio_get_value(colibri_pcmcia_gpio.bvd2_gpio);
+	state->detect = !!gpio_get_value(colibri_pcmcia_gpios[DETECT].gpio);
+	state->ready  = !!gpio_get_value(colibri_pcmcia_gpios[READY].gpio);
+	state->bvd1   = !!gpio_get_value(colibri_pcmcia_gpios[BVD1].gpio);
+	state->bvd2   = !!gpio_get_value(colibri_pcmcia_gpios[BVD2].gpio);
 	state->wrprot = 0;
 	state->vs_3v  = 1;
 	state->vs_Xv  = 0;
@@ -145,9 +109,10 @@ static int
 colibri_pcmcia_configure_socket(struct soc_pcmcia_socket *skt,
 				const socket_state_t *state)
 {
-	gpio_set_value(colibri_pcmcia_gpio.ppen_gpio,
+	gpio_set_value(colibri_pcmcia_gpios[PPEN].gpio,
 			!(state->Vcc == 33 && state->Vpp < 50));
-	gpio_set_value(colibri_pcmcia_gpio.reset_gpio, state->flags & SS_RESET);
+	gpio_set_value(colibri_pcmcia_gpios[RESET].gpio,
+			state->flags & SS_RESET);
 	return 0;
 }
 
@@ -190,20 +155,20 @@ static int __init colibri_pcmcia_init(void)
 
 	/* Colibri PXA270 */
 	if (machine_is_colibri()) {
-		colibri_pcmcia_gpio.reset_gpio	= COLIBRI270_RESET_GPIO;
-		colibri_pcmcia_gpio.ppen_gpio	= COLIBRI270_PPEN_GPIO;
-		colibri_pcmcia_gpio.bvd1_gpio	= COLIBRI270_BVD1_GPIO;
-		colibri_pcmcia_gpio.bvd2_gpio	= COLIBRI270_BVD2_GPIO;
-		colibri_pcmcia_gpio.detect_gpio	= COLIBRI270_DETECT_GPIO;
-		colibri_pcmcia_gpio.ready_gpio	= COLIBRI270_READY_GPIO;
+		colibri_pcmcia_gpios[RESET].gpio	= COLIBRI270_RESET_GPIO;
+		colibri_pcmcia_gpios[PPEN].gpio		= COLIBRI270_PPEN_GPIO;
+		colibri_pcmcia_gpios[BVD1].gpio		= COLIBRI270_BVD1_GPIO;
+		colibri_pcmcia_gpios[BVD2].gpio		= COLIBRI270_BVD2_GPIO;
+		colibri_pcmcia_gpios[DETECT].gpio	= COLIBRI270_DETECT_GPIO;
+		colibri_pcmcia_gpios[READY].gpio	= COLIBRI270_READY_GPIO;
 	/* Colibri PXA320 */
 	} else if (machine_is_colibri320()) {
-		colibri_pcmcia_gpio.reset_gpio	= COLIBRI320_RESET_GPIO;
-		colibri_pcmcia_gpio.ppen_gpio	= COLIBRI320_PPEN_GPIO;
-		colibri_pcmcia_gpio.bvd1_gpio	= COLIBRI320_BVD1_GPIO;
-		colibri_pcmcia_gpio.bvd2_gpio	= COLIBRI320_BVD2_GPIO;
-		colibri_pcmcia_gpio.detect_gpio	= COLIBRI320_DETECT_GPIO;
-		colibri_pcmcia_gpio.ready_gpio	= COLIBRI320_READY_GPIO;
+		colibri_pcmcia_gpios[RESET].gpio	= COLIBRI320_RESET_GPIO;
+		colibri_pcmcia_gpios[PPEN].gpio		= COLIBRI320_PPEN_GPIO;
+		colibri_pcmcia_gpios[BVD1].gpio		= COLIBRI320_BVD1_GPIO;
+		colibri_pcmcia_gpios[BVD2].gpio		= COLIBRI320_BVD2_GPIO;
+		colibri_pcmcia_gpios[DETECT].gpio	= COLIBRI320_DETECT_GPIO;
+		colibri_pcmcia_gpios[READY].gpio	= COLIBRI320_READY_GPIO;
 	}
 
 	ret = platform_device_add_data(colibri_pcmcia_device,

+ 10 - 32
drivers/pcmcia/pxa2xx_palmld.c

@@ -4,7 +4,7 @@
  * Driver for Palm LifeDrive PCMCIA
  *
  * Copyright (C) 2006 Alex Osborne <ato@meshy.org>
- * Copyright (C) 2007-2008 Marek Vasut <marek.vasut@gmail.com>
+ * Copyright (C) 2007-2011 Marek Vasut <marek.vasut@gmail.com>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
@@ -20,49 +20,27 @@
 #include <mach/palmld.h>
 #include "soc_common.h"
 
+static struct gpio palmld_pcmcia_gpios[] = {
+	{ GPIO_NR_PALMLD_PCMCIA_POWER,	GPIOF_INIT_LOW,	"PCMCIA Power" },
+	{ GPIO_NR_PALMLD_PCMCIA_RESET,	GPIOF_INIT_HIGH,"PCMCIA Reset" },
+	{ GPIO_NR_PALMLD_PCMCIA_READY,	GPIOF_IN,	"PCMCIA Ready" },
+};
+
 static int palmld_pcmcia_hw_init(struct soc_pcmcia_socket *skt)
 {
 	int ret;
 
-	ret = gpio_request(GPIO_NR_PALMLD_PCMCIA_POWER, "PCMCIA PWR");
-	if (ret)
-		goto err1;
-	ret = gpio_direction_output(GPIO_NR_PALMLD_PCMCIA_POWER, 0);
-	if (ret)
-		goto err2;
-
-	ret = gpio_request(GPIO_NR_PALMLD_PCMCIA_RESET, "PCMCIA RST");
-	if (ret)
-		goto err2;
-	ret = gpio_direction_output(GPIO_NR_PALMLD_PCMCIA_RESET, 1);
-	if (ret)
-		goto err3;
-
-	ret = gpio_request(GPIO_NR_PALMLD_PCMCIA_READY, "PCMCIA RDY");
-	if (ret)
-		goto err3;
-	ret = gpio_direction_input(GPIO_NR_PALMLD_PCMCIA_READY);
-	if (ret)
-		goto err4;
+	ret = gpio_request_array(palmld_pcmcia_gpios,
+				ARRAY_SIZE(palmld_pcmcia_gpios));
 
 	skt->socket.pci_irq = IRQ_GPIO(GPIO_NR_PALMLD_PCMCIA_READY);
-	return 0;
 
-err4:
-	gpio_free(GPIO_NR_PALMLD_PCMCIA_READY);
-err3:
-	gpio_free(GPIO_NR_PALMLD_PCMCIA_RESET);
-err2:
-	gpio_free(GPIO_NR_PALMLD_PCMCIA_POWER);
-err1:
 	return ret;
 }
 
 static void palmld_pcmcia_hw_shutdown(struct soc_pcmcia_socket *skt)
 {
-	gpio_free(GPIO_NR_PALMLD_PCMCIA_READY);
-	gpio_free(GPIO_NR_PALMLD_PCMCIA_RESET);
-	gpio_free(GPIO_NR_PALMLD_PCMCIA_POWER);
+	gpio_free_array(palmld_pcmcia_gpios, ARRAY_SIZE(palmld_pcmcia_gpios));
 }
 
 static void palmld_pcmcia_socket_state(struct soc_pcmcia_socket *skt,

+ 13 - 62
drivers/pcmcia/pxa2xx_palmtc.c

@@ -4,7 +4,7 @@
  * Driver for Palm Tungsten|C PCMCIA
  *
  * Copyright (C) 2008 Alex Osborne <ato@meshy.org>
- * Copyright (C) 2009 Marek Vasut <marek.vasut@gmail.com>
+ * Copyright (C) 2009-2011 Marek Vasut <marek.vasut@gmail.com>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
@@ -21,79 +21,30 @@
 #include <mach/palmtc.h>
 #include "soc_common.h"
 
+static struct gpio palmtc_pcmcia_gpios[] = {
+	{ GPIO_NR_PALMTC_PCMCIA_POWER1,	GPIOF_INIT_LOW,	"PCMCIA Power 1" },
+	{ GPIO_NR_PALMTC_PCMCIA_POWER2,	GPIOF_INIT_LOW,	"PCMCIA Power 2" },
+	{ GPIO_NR_PALMTC_PCMCIA_POWER3,	GPIOF_INIT_LOW,	"PCMCIA Power 3" },
+	{ GPIO_NR_PALMTC_PCMCIA_RESET,	GPIOF_INIT_HIGH,"PCMCIA Reset" },
+	{ GPIO_NR_PALMTC_PCMCIA_READY,	GPIOF_IN,	"PCMCIA Ready" },
+	{ GPIO_NR_PALMTC_PCMCIA_PWRREADY, GPIOF_IN,	"PCMCIA Power Ready" },
+};
+
 static int palmtc_pcmcia_hw_init(struct soc_pcmcia_socket *skt)
 {
 	int ret;
 
-	ret = gpio_request(GPIO_NR_PALMTC_PCMCIA_POWER1, "PCMCIA PWR1");
-	if (ret)
-		goto err1;
-	ret = gpio_direction_output(GPIO_NR_PALMTC_PCMCIA_POWER1, 0);
-	if (ret)
-		goto err2;
-
-	ret = gpio_request(GPIO_NR_PALMTC_PCMCIA_POWER2, "PCMCIA PWR2");
-	if (ret)
-		goto err2;
-	ret = gpio_direction_output(GPIO_NR_PALMTC_PCMCIA_POWER2, 0);
-	if (ret)
-		goto err3;
-
-	ret = gpio_request(GPIO_NR_PALMTC_PCMCIA_POWER3, "PCMCIA PWR3");
-	if (ret)
-		goto err3;
-	ret = gpio_direction_output(GPIO_NR_PALMTC_PCMCIA_POWER3, 0);
-	if (ret)
-		goto err4;
-
-	ret = gpio_request(GPIO_NR_PALMTC_PCMCIA_RESET, "PCMCIA RST");
-	if (ret)
-		goto err4;
-	ret = gpio_direction_output(GPIO_NR_PALMTC_PCMCIA_RESET, 1);
-	if (ret)
-		goto err5;
-
-	ret = gpio_request(GPIO_NR_PALMTC_PCMCIA_READY, "PCMCIA RDY");
-	if (ret)
-		goto err5;
-	ret = gpio_direction_input(GPIO_NR_PALMTC_PCMCIA_READY);
-	if (ret)
-		goto err6;
-
-	ret = gpio_request(GPIO_NR_PALMTC_PCMCIA_PWRREADY, "PCMCIA PWRRDY");
-	if (ret)
-		goto err6;
-	ret = gpio_direction_input(GPIO_NR_PALMTC_PCMCIA_PWRREADY);
-	if (ret)
-		goto err7;
+	ret = gpio_request_array(palmtc_pcmcia_gpios,
+				ARRAY_SIZE(palmtc_pcmcia_gpios));
 
 	skt->socket.pci_irq = IRQ_GPIO(GPIO_NR_PALMTC_PCMCIA_READY);
-	return 0;
 
-err7:
-	gpio_free(GPIO_NR_PALMTC_PCMCIA_PWRREADY);
-err6:
-	gpio_free(GPIO_NR_PALMTC_PCMCIA_READY);
-err5:
-	gpio_free(GPIO_NR_PALMTC_PCMCIA_RESET);
-err4:
-	gpio_free(GPIO_NR_PALMTC_PCMCIA_POWER3);
-err3:
-	gpio_free(GPIO_NR_PALMTC_PCMCIA_POWER2);
-err2:
-	gpio_free(GPIO_NR_PALMTC_PCMCIA_POWER1);
-err1:
 	return ret;
 }
 
 static void palmtc_pcmcia_hw_shutdown(struct soc_pcmcia_socket *skt)
 {
-	gpio_free(GPIO_NR_PALMTC_PCMCIA_PWRREADY);
-	gpio_free(GPIO_NR_PALMTC_PCMCIA_READY);
-	gpio_free(GPIO_NR_PALMTC_PCMCIA_RESET);
-	gpio_free(GPIO_NR_PALMTC_PCMCIA_POWER3);
-	gpio_free(GPIO_NR_PALMTC_PCMCIA_POWER2);
-	gpio_free(GPIO_NR_PALMTC_PCMCIA_POWER1);
+	gpio_free_array(palmtc_pcmcia_gpios, ARRAY_SIZE(palmtc_pcmcia_gpios));
 }
 
 static void palmtc_pcmcia_socket_state(struct soc_pcmcia_socket *skt,

+ 12 - 45
drivers/pcmcia/pxa2xx_palmtx.c

@@ -3,7 +3,7 @@
  *
  * Driver for Palm T|X PCMCIA
  *
- * Copyright (C) 2007-2008 Marek Vasut <marek.vasut@gmail.com>
+ * Copyright (C) 2007-2011 Marek Vasut <marek.vasut@gmail.com>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
@@ -13,67 +13,34 @@
 
 #include <linux/module.h>
 #include <linux/platform_device.h>
+#include <linux/gpio.h>
 
 #include <asm/mach-types.h>
-
-#include <mach/gpio.h>
 #include <mach/palmtx.h>
-
 #include "soc_common.h"
 
+static struct gpio palmtx_pcmcia_gpios[] = {
+	{ GPIO_NR_PALMTX_PCMCIA_POWER1,	GPIOF_INIT_LOW,	"PCMCIA Power 1" },
+	{ GPIO_NR_PALMTX_PCMCIA_POWER2,	GPIOF_INIT_LOW,	"PCMCIA Power 2" },
+	{ GPIO_NR_PALMTX_PCMCIA_RESET,	GPIOF_INIT_HIGH,"PCMCIA Reset" },
+	{ GPIO_NR_PALMTX_PCMCIA_READY,	GPIOF_IN,	"PCMCIA Ready" },
+};
+
 static int palmtx_pcmcia_hw_init(struct soc_pcmcia_socket *skt)
 {
 	int ret;
 
-	ret = gpio_request(GPIO_NR_PALMTX_PCMCIA_POWER1, "PCMCIA PWR1");
-	if (ret)
-		goto err1;
-	ret = gpio_direction_output(GPIO_NR_PALMTX_PCMCIA_POWER1, 0);
-	if (ret)
-		goto err2;
-
-	ret = gpio_request(GPIO_NR_PALMTX_PCMCIA_POWER2, "PCMCIA PWR2");
-	if (ret)
-		goto err2;
-	ret = gpio_direction_output(GPIO_NR_PALMTX_PCMCIA_POWER2, 0);
-	if (ret)
-		goto err3;
-
-	ret = gpio_request(GPIO_NR_PALMTX_PCMCIA_RESET, "PCMCIA RST");
-	if (ret)
-		goto err3;
-	ret = gpio_direction_output(GPIO_NR_PALMTX_PCMCIA_RESET, 1);
-	if (ret)
-		goto err4;
-
-	ret = gpio_request(GPIO_NR_PALMTX_PCMCIA_READY, "PCMCIA RDY");
-	if (ret)
-		goto err4;
-	ret = gpio_direction_input(GPIO_NR_PALMTX_PCMCIA_READY);
-	if (ret)
-		goto err5;
+	ret = gpio_request_array(palmtx_pcmcia_gpios,
+				ARRAY_SIZE(palmtx_pcmcia_gpios));
 
 	skt->socket.pci_irq = gpio_to_irq(GPIO_NR_PALMTX_PCMCIA_READY);
-	return 0;
 
-err5:
-	gpio_free(GPIO_NR_PALMTX_PCMCIA_READY);
-err4:
-	gpio_free(GPIO_NR_PALMTX_PCMCIA_RESET);
-err3:
-	gpio_free(GPIO_NR_PALMTX_PCMCIA_POWER2);
-err2:
-	gpio_free(GPIO_NR_PALMTX_PCMCIA_POWER1);
-err1:
 	return ret;
 }
 
 static void palmtx_pcmcia_hw_shutdown(struct soc_pcmcia_socket *skt)
 {
-	gpio_free(GPIO_NR_PALMTX_PCMCIA_READY);
-	gpio_free(GPIO_NR_PALMTX_PCMCIA_RESET);
-	gpio_free(GPIO_NR_PALMTX_PCMCIA_POWER2);
-	gpio_free(GPIO_NR_PALMTX_PCMCIA_POWER1);
+	gpio_free_array(palmtx_pcmcia_gpios, ARRAY_SIZE(palmtx_pcmcia_gpios));
 }
 
 static void palmtx_pcmcia_socket_state(struct soc_pcmcia_socket *skt,

+ 30 - 80
drivers/pcmcia/pxa2xx_vpac270.c

@@ -3,8 +3,7 @@
  *
  * Driver for Voipac PXA270 PCMCIA and CF sockets
  *
- * Copyright (C) 2010
- * Marek Vasut <marek.vasut@gmail.com>
+ * Copyright (C) 2010-2011 Marek Vasut <marek.vasut@gmail.com>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
@@ -22,6 +21,19 @@
 
 #include "soc_common.h"
 
+static struct gpio vpac270_pcmcia_gpios[] = {
+	{ GPIO84_VPAC270_PCMCIA_CD,	GPIOF_IN,	"PCMCIA Card Detect" },
+	{ GPIO35_VPAC270_PCMCIA_RDY,	GPIOF_IN,	"PCMCIA Ready" },
+	{ GPIO107_VPAC270_PCMCIA_PPEN,	GPIOF_INIT_LOW,	"PCMCIA PPEN" },
+	{ GPIO11_VPAC270_PCMCIA_RESET,	GPIOF_INIT_LOW,	"PCMCIA Reset" },
+};
+
+static struct gpio vpac270_cf_gpios[] = {
+	{ GPIO17_VPAC270_CF_CD,		GPIOF_IN,	"CF Card Detect" },
+	{ GPIO12_VPAC270_CF_RDY,	GPIOF_IN,	"CF Ready" },
+	{ GPIO16_VPAC270_CF_RESET,	GPIOF_INIT_LOW,	"CF Reset" },
+};
+
 static struct pcmcia_irqs cd_irqs[] = {
 	{
 		.sock = 0,
@@ -40,96 +52,34 @@ static int vpac270_pcmcia_hw_init(struct soc_pcmcia_socket *skt)
 	int ret;
 
 	if (skt->nr == 0) {
-		ret = gpio_request(GPIO84_VPAC270_PCMCIA_CD, "PCMCIA CD");
-		if (ret)
-			goto err1;
-		ret = gpio_direction_input(GPIO84_VPAC270_PCMCIA_CD);
-		if (ret)
-			goto err2;
-
-		ret = gpio_request(GPIO35_VPAC270_PCMCIA_RDY, "PCMCIA RDY");
-		if (ret)
-			goto err2;
-		ret = gpio_direction_input(GPIO35_VPAC270_PCMCIA_RDY);
-		if (ret)
-			goto err3;
-
-		ret = gpio_request(GPIO107_VPAC270_PCMCIA_PPEN, "PCMCIA PPEN");
-		if (ret)
-			goto err3;
-		ret = gpio_direction_output(GPIO107_VPAC270_PCMCIA_PPEN, 0);
-		if (ret)
-			goto err4;
-
-		ret = gpio_request(GPIO11_VPAC270_PCMCIA_RESET, "PCMCIA RESET");
-		if (ret)
-			goto err4;
-		ret = gpio_direction_output(GPIO11_VPAC270_PCMCIA_RESET, 0);
-		if (ret)
-			goto err5;
+		ret = gpio_request_array(vpac270_pcmcia_gpios,
+				ARRAY_SIZE(vpac270_pcmcia_gpios));
 
 		skt->socket.pci_irq = gpio_to_irq(GPIO35_VPAC270_PCMCIA_RDY);
 
-		return soc_pcmcia_request_irqs(skt, &cd_irqs[0], 1);
-
-err5:
-		gpio_free(GPIO11_VPAC270_PCMCIA_RESET);
-err4:
-		gpio_free(GPIO107_VPAC270_PCMCIA_PPEN);
-err3:
-		gpio_free(GPIO35_VPAC270_PCMCIA_RDY);
-err2:
-		gpio_free(GPIO84_VPAC270_PCMCIA_CD);
-err1:
-		return ret;
-
+		if (!ret)
+			ret = soc_pcmcia_request_irqs(skt, &cd_irqs[0], 1);
 	} else {
-		ret = gpio_request(GPIO17_VPAC270_CF_CD, "CF CD");
-		if (ret)
-			goto err6;
-		ret = gpio_direction_input(GPIO17_VPAC270_CF_CD);
-		if (ret)
-			goto err7;
-
-		ret = gpio_request(GPIO12_VPAC270_CF_RDY, "CF RDY");
-		if (ret)
-			goto err7;
-		ret = gpio_direction_input(GPIO12_VPAC270_CF_RDY);
-		if (ret)
-			goto err8;
-
-		ret = gpio_request(GPIO16_VPAC270_CF_RESET, "CF RESET");
-		if (ret)
-			goto err8;
-		ret = gpio_direction_output(GPIO16_VPAC270_CF_RESET, 0);
-		if (ret)
-			goto err9;
+		ret = gpio_request_array(vpac270_cf_gpios,
+				ARRAY_SIZE(vpac270_cf_gpios));
 
 		skt->socket.pci_irq = gpio_to_irq(GPIO12_VPAC270_CF_RDY);
 
-		return soc_pcmcia_request_irqs(skt, &cd_irqs[1], 1);
-
-err9:
-		gpio_free(GPIO16_VPAC270_CF_RESET);
-err8:
-		gpio_free(GPIO12_VPAC270_CF_RDY);
-err7:
-		gpio_free(GPIO17_VPAC270_CF_CD);
-err6:
-		return ret;
-
+		if (!ret)
+			ret = soc_pcmcia_request_irqs(skt, &cd_irqs[1], 1);
 	}
+
+	return ret;
 }
 
 static void vpac270_pcmcia_hw_shutdown(struct soc_pcmcia_socket *skt)
 {
-	gpio_free(GPIO11_VPAC270_PCMCIA_RESET);
-	gpio_free(GPIO107_VPAC270_PCMCIA_PPEN);
-	gpio_free(GPIO35_VPAC270_PCMCIA_RDY);
-	gpio_free(GPIO84_VPAC270_PCMCIA_CD);
-	gpio_free(GPIO16_VPAC270_CF_RESET);
-	gpio_free(GPIO12_VPAC270_CF_RDY);
-	gpio_free(GPIO17_VPAC270_CF_CD);
+	if (skt->nr == 0)
+		gpio_request_array(vpac270_pcmcia_gpios,
+					ARRAY_SIZE(vpac270_pcmcia_gpios));
+	else
+		gpio_request_array(vpac270_cf_gpios,
+					ARRAY_SIZE(vpac270_cf_gpios));
 }
 
 static void vpac270_pcmcia_socket_state(struct soc_pcmcia_socket *skt,

+ 7 - 69
drivers/usb/gadget/pxa25x_udc.c

@@ -139,24 +139,6 @@ static const char ep0name [] = "ep0";
 static void pxa25x_ep_fifo_flush (struct usb_ep *ep);
 static void nuke (struct pxa25x_ep *, int status);
 
-/* one GPIO should be used to detect VBUS from the host */
-static int is_vbus_present(void)
-{
-	struct pxa2xx_udc_mach_info		*mach = the_controller->mach;
-
-	if (gpio_is_valid(mach->gpio_vbus)) {
-		int value = gpio_get_value(mach->gpio_vbus);
-
-		if (mach->gpio_vbus_inverted)
-			return !value;
-		else
-			return !!value;
-	}
-	if (mach->udc_is_connected)
-		return mach->udc_is_connected();
-	return 1;
-}
-
 /* one GPIO should control a D+ pullup, so host sees this device (or not) */
 static void pullup_off(void)
 {
@@ -1055,7 +1037,7 @@ udc_seq_show(struct seq_file *m, void *_d)
 		"%s version: %s\nGadget driver: %s\nHost %s\n\n",
 		driver_name, DRIVER_VERSION SIZE_STR "(pio)",
 		dev->driver ? dev->driver->driver.name : "(none)",
-		is_vbus_present() ? "full speed" : "disconnected");
+		dev->gadget.speed == USB_SPEED_FULL ? "full speed" : "disconnected");
 
 	/* registers for device and ep0 */
 	seq_printf(m,
@@ -1094,7 +1076,7 @@ udc_seq_show(struct seq_file *m, void *_d)
 			(tmp & UDCCFR_ACM) ? " acm" : "");
 	}
 
-	if (!is_vbus_present() || !dev->driver)
+	if (dev->gadget.speed != USB_SPEED_FULL || !dev->driver)
 		goto done;
 
 	seq_printf(m, "ep0 IN %lu/%lu, OUT %lu/%lu\nirqs %lu\n\n",
@@ -1435,14 +1417,6 @@ lubbock_vbus_irq(int irq, void *_dev)
 
 #endif
 
-static irqreturn_t udc_vbus_irq(int irq, void *_dev)
-{
-	struct pxa25x_udc	*dev = _dev;
-
-	pxa25x_udc_vbus_session(&dev->gadget, is_vbus_present());
-	return IRQ_HANDLED;
-}
-
 
 /*-------------------------------------------------------------------------*/
 
@@ -1766,12 +1740,9 @@ pxa25x_udc_irq(int irq, void *_dev)
 		if (unlikely(udccr & UDCCR_SUSIR)) {
 			udc_ack_int_UDCCR(UDCCR_SUSIR);
 			handled = 1;
-			DBG(DBG_VERBOSE, "USB suspend%s\n", is_vbus_present()
-				? "" : "+disconnect");
+			DBG(DBG_VERBOSE, "USB suspend\n");
 
-			if (!is_vbus_present())
-				stop_activity(dev, dev->driver);
-			else if (dev->gadget.speed != USB_SPEED_UNKNOWN
+			if (dev->gadget.speed != USB_SPEED_UNKNOWN
 					&& dev->driver
 					&& dev->driver->suspend)
 				dev->driver->suspend(&dev->gadget);
@@ -1786,8 +1757,7 @@ pxa25x_udc_irq(int irq, void *_dev)
 
 			if (dev->gadget.speed != USB_SPEED_UNKNOWN
 					&& dev->driver
-					&& dev->driver->resume
-					&& is_vbus_present())
+					&& dev->driver->resume)
 				dev->driver->resume(&dev->gadget);
 		}
 
@@ -2137,7 +2107,7 @@ static struct pxa25x_udc memory = {
 static int __init pxa25x_udc_probe(struct platform_device *pdev)
 {
 	struct pxa25x_udc *dev = &memory;
-	int retval, vbus_irq, irq;
+	int retval, irq;
 	u32 chiprev;
 
 	/* insist on Intel/ARM/XScale */
@@ -2199,19 +2169,6 @@ static int __init pxa25x_udc_probe(struct platform_device *pdev)
 
 	dev->transceiver = otg_get_transceiver();
 
-	if (gpio_is_valid(dev->mach->gpio_vbus)) {
-		if ((retval = gpio_request(dev->mach->gpio_vbus,
-				"pxa25x_udc GPIO VBUS"))) {
-			dev_dbg(&pdev->dev,
-				"can't get vbus gpio %d, err: %d\n",
-				dev->mach->gpio_vbus, retval);
-			goto err_gpio_vbus;
-		}
-		gpio_direction_input(dev->mach->gpio_vbus);
-		vbus_irq = gpio_to_irq(dev->mach->gpio_vbus);
-	} else
-		vbus_irq = 0;
-
 	if (gpio_is_valid(dev->mach->gpio_pullup)) {
 		if ((retval = gpio_request(dev->mach->gpio_pullup,
 				"pca25x_udc GPIO PULLUP"))) {
@@ -2237,7 +2194,7 @@ static int __init pxa25x_udc_probe(struct platform_device *pdev)
 	udc_disable(dev);
 	udc_reinit(dev);
 
-	dev->vbus = !!is_vbus_present();
+	dev->vbus = 0;
 
 	/* irq setup after old hardware state is cleaned up */
 	retval = request_irq(irq, pxa25x_udc_irq,
@@ -2273,22 +2230,10 @@ lubbock_fail0:
 		}
 	} else
 #endif
-	if (vbus_irq) {
-		retval = request_irq(vbus_irq, udc_vbus_irq,
-				IRQF_DISABLED | IRQF_SAMPLE_RANDOM |
-				IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
-				driver_name, dev);
-		if (retval != 0) {
-			pr_err("%s: can't get irq %i, err %d\n",
-				driver_name, vbus_irq, retval);
-			goto err_vbus_irq;
-		}
-	}
 	create_debug_files(dev);
 
 	return 0;
 
- err_vbus_irq:
 #ifdef	CONFIG_ARCH_LUBBOCK
 	free_irq(LUBBOCK_USB_DISC_IRQ, dev);
  err_irq_lub:
@@ -2298,9 +2243,6 @@ lubbock_fail0:
 	if (gpio_is_valid(dev->mach->gpio_pullup))
 		gpio_free(dev->mach->gpio_pullup);
  err_gpio_pullup:
-	if (gpio_is_valid(dev->mach->gpio_vbus))
-		gpio_free(dev->mach->gpio_vbus);
- err_gpio_vbus:
 	if (dev->transceiver) {
 		otg_put_transceiver(dev->transceiver);
 		dev->transceiver = NULL;
@@ -2337,10 +2279,6 @@ static int __exit pxa25x_udc_remove(struct platform_device *pdev)
 		free_irq(LUBBOCK_USB_IRQ, dev);
 	}
 #endif
-	if (gpio_is_valid(dev->mach->gpio_vbus)) {
-		free_irq(gpio_to_irq(dev->mach->gpio_vbus), dev);
-		gpio_free(dev->mach->gpio_vbus);
-	}
 	if (gpio_is_valid(dev->mach->gpio_pullup))
 		gpio_free(dev->mach->gpio_pullup);
 

+ 89 - 47
drivers/video/pxafb.c

@@ -627,7 +627,12 @@ static void overlay1fb_enable(struct pxafb_layer *ofb)
 
 static void overlay1fb_disable(struct pxafb_layer *ofb)
 {
-	uint32_t lccr5 = lcd_readl(ofb->fbi, LCCR5);
+	uint32_t lccr5;
+
+	if (!(lcd_readl(ofb->fbi, OVL1C1) & OVLxC1_OEN))
+		return;
+
+	lccr5 = lcd_readl(ofb->fbi, LCCR5);
 
 	lcd_writel(ofb->fbi, OVL1C1, ofb->control[0] & ~OVLxC1_OEN);
 
@@ -685,7 +690,12 @@ static void overlay2fb_enable(struct pxafb_layer *ofb)
 
 static void overlay2fb_disable(struct pxafb_layer *ofb)
 {
-	uint32_t lccr5 = lcd_readl(ofb->fbi, LCCR5);
+	uint32_t lccr5;
+
+	if (!(lcd_readl(ofb->fbi, OVL2C1) & OVLxC1_OEN))
+		return;
+
+	lccr5 = lcd_readl(ofb->fbi, LCCR5);
 
 	lcd_writel(ofb->fbi, OVL2C1, ofb->control[0] & ~OVLxC1_OEN);
 
@@ -720,12 +730,10 @@ static int overlayfb_open(struct fb_info *info, int user)
 	if (user == 0)
 		return -ENODEV;
 
-	/* allow only one user at a time */
-	if (atomic_inc_and_test(&ofb->usage))
-		return -EBUSY;
+	if (ofb->usage++ == 0)
+		/* unblank the base framebuffer */
+		fb_blank(&ofb->fbi->fb, FB_BLANK_UNBLANK);
 
-	/* unblank the base framebuffer */
-	fb_blank(&ofb->fbi->fb, FB_BLANK_UNBLANK);
 	return 0;
 }
 
@@ -733,12 +741,15 @@ static int overlayfb_release(struct fb_info *info, int user)
 {
 	struct pxafb_layer *ofb = (struct pxafb_layer*) info;
 
-	atomic_dec(&ofb->usage);
-	ofb->ops->disable(ofb);
+	if (ofb->usage == 1) {
+		ofb->ops->disable(ofb);
+		ofb->fb.var.height	= -1;
+		ofb->fb.var.width	= -1;
+		ofb->fb.var.xres = ofb->fb.var.xres_virtual = 0;
+		ofb->fb.var.yres = ofb->fb.var.yres_virtual = 0;
 
-	free_pages_exact(ofb->video_mem, ofb->video_mem_size);
-	ofb->video_mem = NULL;
-	ofb->video_mem_size = 0;
+		ofb->usage--;
+	}
 	return 0;
 }
 
@@ -750,7 +761,7 @@ static int overlayfb_check_var(struct fb_var_screeninfo *var,
 	int xpos, ypos, pfor, bpp;
 
 	xpos = NONSTD_TO_XPOS(var->nonstd);
-	ypos = NONSTD_TO_XPOS(var->nonstd);
+	ypos = NONSTD_TO_YPOS(var->nonstd);
 	pfor = NONSTD_TO_PFOR(var->nonstd);
 
 	bpp = pxafb_var_to_bpp(var);
@@ -794,7 +805,7 @@ static int overlayfb_check_var(struct fb_var_screeninfo *var,
 	return 0;
 }
 
-static int overlayfb_map_video_memory(struct pxafb_layer *ofb)
+static int overlayfb_check_video_memory(struct pxafb_layer *ofb)
 {
 	struct fb_var_screeninfo *var = &ofb->fb.var;
 	int pfor = NONSTD_TO_PFOR(var->nonstd);
@@ -812,27 +823,11 @@ static int overlayfb_map_video_memory(struct pxafb_layer *ofb)
 
 	size = PAGE_ALIGN(ofb->fb.fix.line_length * var->yres_virtual);
 
-	/* don't re-allocate if the original video memory is enough */
 	if (ofb->video_mem) {
 		if (ofb->video_mem_size >= size)
 			return 0;
-
-		free_pages_exact(ofb->video_mem, ofb->video_mem_size);
 	}
-
-	ofb->video_mem = alloc_pages_exact(size, GFP_KERNEL | __GFP_ZERO);
-	if (ofb->video_mem == NULL)
-		return -ENOMEM;
-
-	ofb->video_mem_phys = virt_to_phys(ofb->video_mem);
-	ofb->video_mem_size = size;
-
-	mutex_lock(&ofb->fb.mm_lock);
-	ofb->fb.fix.smem_start	= ofb->video_mem_phys;
-	ofb->fb.fix.smem_len	= ofb->fb.fix.line_length * var->yres_virtual;
-	mutex_unlock(&ofb->fb.mm_lock);
-	ofb->fb.screen_base	= ofb->video_mem;
-	return 0;
+	return -EINVAL;
 }
 
 static int overlayfb_set_par(struct fb_info *info)
@@ -841,13 +836,13 @@ static int overlayfb_set_par(struct fb_info *info)
 	struct fb_var_screeninfo *var = &info->var;
 	int xpos, ypos, pfor, bpp, ret;
 
-	ret = overlayfb_map_video_memory(ofb);
+	ret = overlayfb_check_video_memory(ofb);
 	if (ret)
 		return ret;
 
 	bpp  = pxafb_var_to_bpp(var);
 	xpos = NONSTD_TO_XPOS(var->nonstd);
-	ypos = NONSTD_TO_XPOS(var->nonstd);
+	ypos = NONSTD_TO_YPOS(var->nonstd);
 	pfor = NONSTD_TO_PFOR(var->nonstd);
 
 	ofb->control[0] = OVLxC1_PPL(var->xres) | OVLxC1_LPO(var->yres) |
@@ -891,7 +886,7 @@ static void __devinit init_pxafb_overlay(struct pxafb_info *fbi,
 
 	ofb->id = id;
 	ofb->ops = &ofb_ops[id];
-	atomic_set(&ofb->usage, 0);
+	ofb->usage = 0;
 	ofb->fbi = fbi;
 	init_completion(&ofb->branch_done);
 }
@@ -904,29 +899,60 @@ static inline int pxafb_overlay_supported(void)
 	return 0;
 }
 
-static int __devinit pxafb_overlay_init(struct pxafb_info *fbi)
+static int __devinit pxafb_overlay_map_video_memory(struct pxafb_info *pxafb,
+	struct pxafb_layer *ofb)
+{
+	/* We assume that user will use at most video_mem_size for overlay fb,
+	 * anyway, it's useless to use 16bpp main plane and 24bpp overlay
+	 */
+	ofb->video_mem = alloc_pages_exact(PAGE_ALIGN(pxafb->video_mem_size),
+		GFP_KERNEL | __GFP_ZERO);
+	if (ofb->video_mem == NULL)
+		return -ENOMEM;
+
+	ofb->video_mem_phys = virt_to_phys(ofb->video_mem);
+	ofb->video_mem_size = PAGE_ALIGN(pxafb->video_mem_size);
+
+	mutex_lock(&ofb->fb.mm_lock);
+	ofb->fb.fix.smem_start	= ofb->video_mem_phys;
+	ofb->fb.fix.smem_len	= pxafb->video_mem_size;
+	mutex_unlock(&ofb->fb.mm_lock);
+
+	ofb->fb.screen_base	= ofb->video_mem;
+
+	return 0;
+}
+
+static void __devinit pxafb_overlay_init(struct pxafb_info *fbi)
 {
 	int i, ret;
 
 	if (!pxafb_overlay_supported())
-		return 0;
+		return;
 
 	for (i = 0; i < 2; i++) {
-		init_pxafb_overlay(fbi, &fbi->overlay[i], i);
-		ret = register_framebuffer(&fbi->overlay[i].fb);
+		struct pxafb_layer *ofb = &fbi->overlay[i];
+		init_pxafb_overlay(fbi, ofb, i);
+		ret = register_framebuffer(&ofb->fb);
 		if (ret) {
 			dev_err(fbi->dev, "failed to register overlay %d\n", i);
-			return ret;
+			continue;
 		}
+		ret = pxafb_overlay_map_video_memory(fbi, ofb);
+		if (ret) {
+			dev_err(fbi->dev,
+				"failed to map video memory for overlay %d\n",
+				i);
+			unregister_framebuffer(&ofb->fb);
+			continue;
+		}
+		ofb->registered = 1;
 	}
 
 	/* mask all IU/BS/EOF/SOF interrupts */
 	lcd_writel(fbi, LCCR5, ~0);
 
-	/* place overlay(s) on top of base */
-	fbi->lccr0 |= LCCR0_OUC;
 	pr_info("PXA Overlay driver loaded successfully!\n");
-	return 0;
 }
 
 static void __devexit pxafb_overlay_exit(struct pxafb_info *fbi)
@@ -936,8 +962,15 @@ static void __devexit pxafb_overlay_exit(struct pxafb_info *fbi)
 	if (!pxafb_overlay_supported())
 		return;
 
-	for (i = 0; i < 2; i++)
-		unregister_framebuffer(&fbi->overlay[i].fb);
+	for (i = 0; i < 2; i++) {
+		struct pxafb_layer *ofb = &fbi->overlay[i];
+		if (ofb->registered) {
+			if (ofb->video_mem)
+				free_pages_exact(ofb->video_mem,
+					ofb->video_mem_size);
+			unregister_framebuffer(&ofb->fb);
+		}
+	}
 }
 #else
 static inline void pxafb_overlay_init(struct pxafb_info *fbi) {}
@@ -1368,7 +1401,8 @@ static int pxafb_activate_var(struct fb_var_screeninfo *var,
 	    (lcd_readl(fbi, LCCR3) != fbi->reg_lccr3) ||
 	    (lcd_readl(fbi, LCCR4) != fbi->reg_lccr4) ||
 	    (lcd_readl(fbi, FDADR0) != fbi->fdadr[0]) ||
-	    (lcd_readl(fbi, FDADR1) != fbi->fdadr[1]))
+	    ((fbi->lccr0 & LCCR0_SDS) &&
+	    (lcd_readl(fbi, FDADR1) != fbi->fdadr[1])))
 		pxafb_schedule_work(fbi, C_REENABLE);
 
 	return 0;
@@ -1420,7 +1454,8 @@ static void pxafb_enable_controller(struct pxafb_info *fbi)
 	lcd_writel(fbi, LCCR0, fbi->reg_lccr0 & ~LCCR0_ENB);
 
 	lcd_writel(fbi, FDADR0, fbi->fdadr[0]);
-	lcd_writel(fbi, FDADR1, fbi->fdadr[1]);
+	if (fbi->lccr0 & LCCR0_SDS)
+		lcd_writel(fbi, FDADR1, fbi->fdadr[1]);
 	lcd_writel(fbi, LCCR0, fbi->reg_lccr0 | LCCR0_ENB);
 }
 
@@ -1613,7 +1648,8 @@ pxafb_freq_transition(struct notifier_block *nb, unsigned long val, void *data)
 
 	switch (val) {
 	case CPUFREQ_PRECHANGE:
-		set_ctrlr_state(fbi, C_DISABLE_CLKCHANGE);
+		if (!fbi->overlay[0].usage && !fbi->overlay[1].usage)
+			set_ctrlr_state(fbi, C_DISABLE_CLKCHANGE);
 		break;
 
 	case CPUFREQ_POSTCHANGE:
@@ -1806,6 +1842,12 @@ static struct pxafb_info * __devinit pxafb_init_fbinfo(struct device *dev)
 
 	pxafb_decode_mach_info(fbi, inf);
 
+#ifdef CONFIG_FB_PXA_OVERLAY
+	/* place overlay(s) on top of base */
+	if (pxafb_overlay_supported())
+		fbi->lccr0 |= LCCR0_OUC;
+#endif
+
 	init_waitqueue_head(&fbi->ctrlr_wait);
 	INIT_WORK(&fbi->task, pxafb_task);
 	mutex_init(&fbi->ctrlr_lock);

+ 2 - 1
drivers/video/pxafb.h

@@ -92,7 +92,8 @@ struct pxafb_layer_ops {
 struct pxafb_layer {
 	struct fb_info		fb;
 	int			id;
-	atomic_t		usage;
+	int			registered;
+	uint32_t		usage;
 	uint32_t		control[2];
 
 	struct pxafb_layer_ops	*ops;