#
# Patch managed by http://www.mn-logistik.de/unsupported/pxa250/patcher
#

Index: linux-2.6.21/drivers/leds/Kconfig
===================================================================
--- linux-2.6.21.orig/drivers/leds/Kconfig	2007-08-01 20:03:29.000000000 -0300
+++ linux-2.6.21/drivers/leds/Kconfig	2007-08-01 20:04:02.000000000 -0300
@@ -111,6 +111,13 @@
 	  This option enables support for the LEDs on the
 	  Motorola A780 GSM Phone.
 
+config LEDS_E680
+	tristate "LED Support for the Motorola E680(i) GSM Phone"
+	depends LEDS_CLASS && PXA_EZX_E680
+	help
+	  This options enables support for the LEDs on the
+	  Motorola E680(i) GSM Phone.
+
 config LEDS_TRIGGER_TIMER
 	tristate "LED Timer Trigger"
 	depends on LEDS_TRIGGERS
Index: linux-2.6.21/drivers/leds/Makefile
===================================================================
--- linux-2.6.21.orig/drivers/leds/Makefile	2007-08-01 20:03:29.000000000 -0300
+++ linux-2.6.21/drivers/leds/Makefile	2007-08-01 20:04:02.000000000 -0300
@@ -17,6 +17,7 @@
 obj-$(CONFIG_LEDS_H1940)		+= leds-h1940.o
 obj-$(CONFIG_LEDS_COBALT)		+= leds-cobalt.o
 obj-$(CONFIG_LEDS_A780)		+= leds-a780.o
+obj-$(CONFIG_LEDS_E680)		+= leds-e680.o
 
 # LED Triggers
 obj-$(CONFIG_LEDS_TRIGGER_TIMER)	+= ledtrig-timer.o
Index: linux-2.6.21/drivers/leds/leds-e680.c
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ linux-2.6.21/drivers/leds/leds-e680.c	2007-08-01 20:04:02.000000000 -0300
@@ -0,0 +1,235 @@
+/*
+ * EZX Platform LED Driver for the Motorola E680(i) GSM Phone
+ *
+ * Copyright 2006 Vanille-Media
+ *
+ * Author: Michael Lauer <mickey@Vanille.de>
+ *
+ * Based on the Motorola 2.4 leds-e680.c and leds-corgi.c by Richard Purdie
+ *
+ * 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
+ * published by the Free Software Foundation.
+ *
+ */
+
+#include <linux/delay.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/leds.h>
+#include <asm/mach-types.h>
+#include <asm/arch/hardware.h>
+#include <asm/arch/pxa-regs.h>
+#include <asm/arch/ezx-pcap.h>
+
+//FIXME move defines to a common header file
+#define IND_CNTL_R_BUL     46
+#define IND_CNTL_G_BUL     47
+#define SSP_PCAP_LED_MASK  0x000fffe0
+#define SSP_PCAP_LED_SHIFT 5
+#define GPIO_TC_MM_EN      99
+
+extern int ezx_pcap_read(u_int8_t, u_int32_t *);
+extern int ezx_pcap_write(u_int8_t, u_int32_t);
+
+typedef struct {
+	u_int8_t ind_GPIO_red;    /*Indicator Red control GPIO 46: 0 active, 1 inactive */
+	u_int8_t ind_GPIO_green;  /*Indicator Green control GPIO 47: 0 inactive, 1 active */
+	u_int8_t pcap_LEDR_en;    /*pcap LEDR_EN bit value: 1 =Red LED(&Green) sink circuit enabled*/
+	u_int8_t pcap_LEDG_en;    /*pcap LEDG_EN bit value:1 =Green(->Blue)LED sink circuit enabled*/
+	u_int8_t pcap_LEDR_CTRL; /* 4bits Sets the timing for the red(&Green) LED sink circuit*/
+	u_int8_t pcap_LEDG_CTRL; /* 4bits Sets the timing for the GREEN (->Blue) LED sink circuit*/
+	u_int8_t pcap_LEDR_I;   /* 2 bits 00 3mA,01 4mA, 10 5mA, 11 9mA, sets the pulsed current level for LEDR*/
+	u_int8_t pcap_LEDG_I;   /* 2 bits 00 3mA,01 4mA, 10 5mA, 11 9mA, sets the pulsed current level for LEDG*/
+//	u_int8_t pcap_SKIP_on;  /*1=The ON timing sequence defined by LEDx_CTRL is executed on every other cycle*/
+} PCAP2_LED_REGISTER_VALUE;
+
+const PCAP2_LED_REGISTER_VALUE led_register_value[]=
+{
+	{0x1,0x0, 0x0,0x0, 0x0,0x0, 0x1,0x0}, /* 0 OFF */
+
+	{0x0,0x0, 0x1,0x0, 0xf,0x0, 0x1,0x0}, /* 1 RED */
+	{0x1,0x1, 0x1,0x0, 0xf,0x0, 0x1,0x0}, /* 2 GREEN */
+	{0x0,0x1, 0x1,0x0, 0xf,0x0, 0x1,0x0}, /* 3 ORANGE */
+	{0x1,0x0, 0x0,0x1, 0x0,0xf, 0x0,0x0}, /* 4 BLUE */
+	{0x0,0x0, 0x1,0x1, 0xf,0xf, 0x1,0x0}, /* 5 MAGENTA */
+	{0x1,0x1, 0x1,0x1, 0xf,0xf, 0x1,0x0}, /* 6 CYAN */
+	{0x0,0x1, 0x1,0x1, 0xf,0xf, 0x1,0x0}, /* 7 WHITE */
+};
+
+static void e680led_set(struct led_classdev *led_cdev, enum led_brightness value)
+{
+	unsigned int tempValue;
+	unsigned char gpio_red, gpio_green, ledr_en, ledg_en, ledr_ctrl,
+			ledg_ctrl, ledr_i, ledg_i, skip, t, color;
+	unsigned char t_mask[2] = { 0xc, 0xc };
+
+	skip = 0;
+	if (value & 128) {
+		value &= (~128);
+		skip = 1;
+	}
+
+	/* 7 colors - simple on */
+	if (value <= 7)
+		color = value;
+	/* 4 colors - 11 timed on */
+	else if (value <= 51) {
+		value -= 7;
+		color = ((value-1)%4)+1;
+		t = ((value-1)/4)+1;
+		t_mask[0] = t;
+		t_mask[1] = t;
+	}
+	/* 3 colors - 22 change color */
+	else if (value <= 84) {
+		value -= 51;
+		color = ((value-1)%3)+5;
+		t = ((value-1)/3)+1;
+		t_mask[1] = t;
+	}
+	else if (value <= 117) {
+		value -= 84;
+		color = ((value-1)%3)+5;
+		t = ((value-1)/3)+1;
+		t_mask[0] = t;
+	}
+	/* 3 colors - alternate with blue */
+	else if (value <= 120) {
+		color = value-113;
+		t_mask[0] = 0xa;
+		t_mask[1] = 0xb;
+	}
+	/* invalid value */
+	else
+		color = 1;
+
+	gpio_red   = led_register_value[color].ind_GPIO_red;
+	gpio_green = led_register_value[color].ind_GPIO_green;
+	ledr_en    = led_register_value[color].pcap_LEDR_en;
+	ledg_en    = led_register_value[color].pcap_LEDG_en;
+	ledr_ctrl  = led_register_value[color].pcap_LEDR_CTRL & t_mask[0];
+	ledg_ctrl  = led_register_value[color].pcap_LEDG_CTRL & t_mask[1];
+	ledr_i     = led_register_value[color].pcap_LEDR_I;
+	ledg_i     = led_register_value[color].pcap_LEDG_I;
+
+	ezx_pcap_read(SSP_PCAP_ADJ_PERIPH_REGISTER,&tempValue);
+
+	tempValue &= (~SSP_PCAP_LED_MASK);
+
+	pxa_gpio_set_value(IND_CNTL_R_BUL, gpio_red);
+	pxa_gpio_set_value(IND_CNTL_G_BUL, gpio_green);
+
+	/* Write PCAP LED Peripheral Control Register*/
+	tempValue = ((ledr_en | (ledg_en << 1) | (ledr_ctrl << 2) |
+		(ledg_ctrl << 6) | (ledr_i << 10) | (ledg_i << 12) |
+		(skip << 14)) & 0x7fff) << SSP_PCAP_LED_SHIFT;
+
+	ezx_pcap_write(SSP_PCAP_ADJ_PERIPH_REGISTER,tempValue);
+}
+
+static void e680led_keypad_set(struct led_classdev *led_cdev, enum led_brightness value)
+{
+	/* this is not working yet, as there is something else missing */
+#if 0
+	printk( KERN_DEBUG "e680led_keypad_set: %d\n", value );
+
+	pxa_gpio_mode(GPIO_TC_MM_EN);
+	GPDR(GPIO_TC_MM_EN)   |= GPIO_bit(GPIO_TC_MM_EN);
+	GPSR(GPIO_TC_MM_EN)   = GPIO_bit(GPIO_TC_MM_EN);
+
+	udelay( 100 );
+
+    if ( value ) {
+		GPCR(GPIO_TC_MM_EN)   = GPIO_bit(GPIO_TC_MM_EN);
+		PGSR3 &= ~GPIO_bit(GPIO_TC_MM_EN);
+    } else {
+		GPSR(GPIO_TC_MM_EN)   = GPIO_bit(GPIO_TC_MM_EN);
+		PGSR3 |= GPIO_bit(GPIO_TC_MM_EN);
+    }
+#endif
+}
+
+static struct led_classdev e680_led = {
+	.name			= "e680:led",
+	.default_trigger	= "none",
+	.brightness_set		= e680led_set,
+};
+
+static struct led_classdev e680_keypad = {
+	.name			= "e680:keypad",
+	.default_trigger	= "none",
+	.brightness_set		= e680led_keypad_set,
+};
+
+#ifdef CONFIG_PM
+static int e680led_suspend(struct platform_device *dev, pm_message_t state)
+{
+	led_classdev_suspend(&e680_led);
+	led_classdev_suspend(&e680_keypad);
+	return 0;
+}
+
+static int e680led_resume(struct platform_device *dev)
+{
+	led_classdev_resume(&e680_led);
+	led_classdev_resume(&e680_keypad);
+	return 0;
+}
+#endif
+
+static int e680led_probe(struct platform_device *pdev)
+{
+	int ret;
+
+	/* configure GPIOs as output */
+	pxa_gpio_mode(IND_CNTL_R_BUL | GPIO_OUT);
+	pxa_gpio_mode(IND_CNTL_G_BUL | GPIO_OUT);
+
+	ret = led_classdev_register(&pdev->dev, &e680_led);
+	if (ret < 0)
+		return ret;
+
+	ret = led_classdev_register(&pdev->dev, &e680_keypad);
+	if (ret < 0) {
+		led_classdev_unregister(&e680_led);
+	}
+	return ret;
+}
+
+static int e680led_remove(struct platform_device *pdev)
+{
+	led_classdev_unregister(&e680_led);
+	led_classdev_unregister(&e680_keypad);
+	return 0;
+}
+
+static struct platform_driver e680led_driver = {
+	.probe		= e680led_probe,
+	.remove		= e680led_remove,
+#ifdef CONFIG_PM
+	.suspend	= e680led_suspend,
+	.resume		= e680led_resume,
+#endif
+	.driver		= {
+		.name		= "e680-led",
+	},
+};
+
+static int __init e680led_init(void)
+{
+	return platform_driver_register(&e680led_driver);
+}
+
+static void __exit e680led_exit(void)
+{
+	platform_driver_unregister(&e680led_driver);
+}
+
+module_init(e680led_init);
+module_exit(e680led_exit);
+
+MODULE_AUTHOR("Michael Lauer <mickey@Vanille.de>");
+MODULE_DESCRIPTION("Motorola E680 LED driver");
+MODULE_LICENSE("GPL");
Index: linux-2.6.21/arch/arm/mach-pxa/ezx-e680.c
===================================================================
--- linux-2.6.21.orig/arch/arm/mach-pxa/ezx-e680.c	2007-08-01 20:02:32.000000000 -0300
+++ linux-2.6.21/arch/arm/mach-pxa/ezx-e680.c	2007-08-01 20:04:02.000000000 -0300
@@ -347,11 +347,20 @@
        },
 };
 
+static struct platform_device e680led_device = {
+	.name		= "e680-led",
+	.id		= -1,
+	.dev		= {
+		.parent = &e680_pcap_device.dev,
+	},
+};
+
 static struct platform_device *devices[] __initdata = {
 	&e680_pcap_device,
 	&e680_emu_device,
 	&pcap_ts_device,
 	&e680locksw_device,
+	&e680led_device,
 };
 
 static void __init e680_init(void)