diff --git a/drivers/input/keyboard/adp5588-keys.c b/drivers/input/keyboard/adp5588-keys.c
index 4771ab172b59b22dda93eaa5437aba8019d7a208..4ef789ef104242712d14107f3834b59a39965040 100644
--- a/drivers/input/keyboard/adp5588-keys.c
+++ b/drivers/input/keyboard/adp5588-keys.c
@@ -67,6 +67,8 @@ struct adp5588_kpad {
 	struct delayed_work work;
 	unsigned long delay;
 	unsigned short keycode[ADP5588_KEYMAPSIZE];
+	const struct adp5588_gpi_map *gpimap;
+	unsigned short gpimapsize;
 };
 
 static int adp5588_read(struct i2c_client *client, u8 reg)
@@ -84,12 +86,37 @@ static int adp5588_write(struct i2c_client *client, u8 reg, u8 val)
 	return i2c_smbus_write_byte_data(client, reg, val);
 }
 
+static void adp5588_report_events(struct adp5588_kpad *kpad, int ev_cnt)
+{
+	int i, j;
+
+	for (i = 0; i < ev_cnt; i++) {
+		int key = adp5588_read(kpad->client, Key_EVENTA + i);
+		int key_val = key & KEY_EV_MASK;
+
+		if (key_val >= GPI_PIN_BASE && key_val <= GPI_PIN_END) {
+			for (j = 0; j < kpad->gpimapsize; j++) {
+				if (key_val == kpad->gpimap[j].pin) {
+					input_report_switch(kpad->input,
+							kpad->gpimap[j].sw_evt,
+							key & KEY_EV_PRESSED);
+					break;
+				}
+			}
+		} else {
+			input_report_key(kpad->input,
+					 kpad->keycode[key_val - 1],
+					 key & KEY_EV_PRESSED);
+		}
+	}
+}
+
 static void adp5588_work(struct work_struct *work)
 {
 	struct adp5588_kpad *kpad = container_of(work,
 						struct adp5588_kpad, work.work);
 	struct i2c_client *client = kpad->client;
-	int i, key, status, ev_cnt;
+	int status, ev_cnt;
 
 	status = adp5588_read(client, INT_STAT);
 
@@ -99,12 +126,7 @@ static void adp5588_work(struct work_struct *work)
 	if (status & KE_INT) {
 		ev_cnt = adp5588_read(client, KEY_LCK_EC_STAT) & KEC;
 		if (ev_cnt) {
-			for (i = 0; i < ev_cnt; i++) {
-				key = adp5588_read(client, Key_EVENTA + i);
-				input_report_key(kpad->input,
-					kpad->keycode[(key & KEY_EV_MASK) - 1],
-					key & KEY_EV_PRESSED);
-			}
+			adp5588_report_events(kpad, ev_cnt);
 			input_sync(kpad->input);
 		}
 	}
@@ -130,6 +152,7 @@ static int __devinit adp5588_setup(struct i2c_client *client)
 {
 	struct adp5588_kpad_platform_data *pdata = client->dev.platform_data;
 	int i, ret;
+	unsigned char evt_mode1 = 0, evt_mode2 = 0, evt_mode3 = 0;
 
 	ret = adp5588_write(client, KP_GPIO1, KP_SEL(pdata->rows));
 	ret |= adp5588_write(client, KP_GPIO2, KP_SEL(pdata->cols) & 0xFF);
@@ -144,6 +167,23 @@ static int __devinit adp5588_setup(struct i2c_client *client)
 	for (i = 0; i < KEYP_MAX_EVENT; i++)
 		ret |= adp5588_read(client, Key_EVENTA);
 
+	for (i = 0; i < pdata->gpimapsize; i++) {
+		unsigned short pin = pdata->gpimap[i].pin;
+
+		if (pin <= GPI_PIN_ROW_END) {
+			evt_mode1 |= (1 << (pin - GPI_PIN_ROW_BASE));
+		} else {
+			evt_mode2 |= ((1 << (pin - GPI_PIN_COL_BASE)) & 0xFF);
+			evt_mode3 |= ((1 << (pin - GPI_PIN_COL_BASE)) >> 8);
+		}
+	}
+
+	if (pdata->gpimapsize) {
+		ret |= adp5588_write(client, GPI_EM1, evt_mode1);
+		ret |= adp5588_write(client, GPI_EM2, evt_mode2);
+		ret |= adp5588_write(client, GPI_EM3, evt_mode3);
+	}
+
 	ret |= adp5588_write(client, INT_STAT, CMP2_INT | CMP1_INT |
 					OVR_FLOW_INT | K_LCK_INT |
 					GPI_INT | KE_INT); /* Status is W1C */
@@ -158,6 +198,44 @@ static int __devinit adp5588_setup(struct i2c_client *client)
 	return 0;
 }
 
+static void __devinit adp5588_report_switch_state(struct adp5588_kpad *kpad)
+{
+	int gpi_stat1 = adp5588_read(kpad->client, GPIO_DAT_STAT1);
+	int gpi_stat2 = adp5588_read(kpad->client, GPIO_DAT_STAT2);
+	int gpi_stat3 = adp5588_read(kpad->client, GPIO_DAT_STAT3);
+	int gpi_stat_tmp, pin_loc;
+	int i;
+
+	for (i = 0; i < kpad->gpimapsize; i++) {
+		unsigned short pin = kpad->gpimap[i].pin;
+
+		if (pin <= GPI_PIN_ROW_END) {
+			gpi_stat_tmp = gpi_stat1;
+			pin_loc = pin - GPI_PIN_ROW_BASE;
+		} else if ((pin - GPI_PIN_COL_BASE) < 8) {
+			gpi_stat_tmp = gpi_stat2;
+			pin_loc = pin - GPI_PIN_COL_BASE;
+		} else {
+			gpi_stat_tmp = gpi_stat3;
+			pin_loc = pin - GPI_PIN_COL_BASE - 8;
+		}
+
+		if (gpi_stat_tmp < 0) {
+			dev_err(&kpad->client->dev,
+				"Can't read GPIO_DAT_STAT switch %d default to OFF\n",
+				pin);
+			gpi_stat_tmp = 0;
+		}
+
+		input_report_switch(kpad->input,
+				    kpad->gpimap[i].sw_evt,
+				    !(gpi_stat_tmp & (1 << pin_loc)));
+	}
+
+	input_sync(kpad->input);
+}
+
+
 static int __devinit adp5588_probe(struct i2c_client *client,
 					const struct i2c_device_id *id)
 {
@@ -189,6 +267,37 @@ static int __devinit adp5588_probe(struct i2c_client *client,
 		return -EINVAL;
 	}
 
+	if (!pdata->gpimap && pdata->gpimapsize) {
+		dev_err(&client->dev, "invalid gpimap from pdata\n");
+		return -EINVAL;
+	}
+
+	if (pdata->gpimapsize > ADP5588_GPIMAPSIZE_MAX) {
+		dev_err(&client->dev, "invalid gpimapsize\n");
+		return -EINVAL;
+	}
+
+	for (i = 0; i < pdata->gpimapsize; i++) {
+		unsigned short pin = pdata->gpimap[i].pin;
+
+		if (pin < GPI_PIN_BASE || pin > GPI_PIN_END) {
+			dev_err(&client->dev, "invalid gpi pin data\n");
+			return -EINVAL;
+		}
+
+		if (pin <= GPI_PIN_ROW_END) {
+			if (pin - GPI_PIN_ROW_BASE + 1 <= pdata->rows) {
+				dev_err(&client->dev, "invalid gpi row data\n");
+				return -EINVAL;
+			}
+		} else {
+			if (pin - GPI_PIN_COL_BASE + 1 <= pdata->cols) {
+				dev_err(&client->dev, "invalid gpi col data\n");
+				return -EINVAL;
+			}
+		}
+	}
+
 	if (!client->irq) {
 		dev_err(&client->dev, "no IRQ?\n");
 		return -EINVAL;
@@ -233,6 +342,9 @@ static int __devinit adp5588_probe(struct i2c_client *client,
 	memcpy(kpad->keycode, pdata->keymap,
 		pdata->keymapsize * input->keycodesize);
 
+	kpad->gpimap = pdata->gpimap;
+	kpad->gpimapsize = pdata->gpimapsize;
+
 	/* setup input device */
 	__set_bit(EV_KEY, input->evbit);
 
@@ -243,6 +355,11 @@ static int __devinit adp5588_probe(struct i2c_client *client,
 		__set_bit(kpad->keycode[i] & KEY_MAX, input->keybit);
 	__clear_bit(KEY_RESERVED, input->keybit);
 
+	if (kpad->gpimapsize)
+		__set_bit(EV_SW, input->evbit);
+	for (i = 0; i < kpad->gpimapsize; i++)
+		__set_bit(kpad->gpimap[i].sw_evt, input->swbit);
+
 	error = input_register_device(input);
 	if (error) {
 		dev_err(&client->dev, "unable to register input device\n");
@@ -261,6 +378,9 @@ static int __devinit adp5588_probe(struct i2c_client *client,
 	if (error)
 		goto err_free_irq;
 
+	if (kpad->gpimapsize)
+		adp5588_report_switch_state(kpad);
+
 	device_init_wakeup(&client->dev, 1);
 	i2c_set_clientdata(client, kpad);
 
diff --git a/include/linux/i2c/adp5588.h b/include/linux/i2c/adp5588.h
index 02c9af374741835efb1feaa1cd0c4f7bcc7e80dd..b5f57c498e24d871f2a6a51ac49e9fd88ae7aa89 100644
--- a/include/linux/i2c/adp5588.h
+++ b/include/linux/i2c/adp5588.h
@@ -78,6 +78,40 @@
 
 #define ADP5588_KEYMAPSIZE	80
 
+#define GPI_PIN_ROW0 97
+#define GPI_PIN_ROW1 98
+#define GPI_PIN_ROW2 99
+#define GPI_PIN_ROW3 100
+#define GPI_PIN_ROW4 101
+#define GPI_PIN_ROW5 102
+#define GPI_PIN_ROW6 103
+#define GPI_PIN_ROW7 104
+#define GPI_PIN_COL0 105
+#define GPI_PIN_COL1 106
+#define GPI_PIN_COL2 107
+#define GPI_PIN_COL3 108
+#define GPI_PIN_COL4 109
+#define GPI_PIN_COL5 110
+#define GPI_PIN_COL6 111
+#define GPI_PIN_COL7 112
+#define GPI_PIN_COL8 113
+#define GPI_PIN_COL9 114
+
+#define GPI_PIN_ROW_BASE GPI_PIN_ROW0
+#define GPI_PIN_ROW_END GPI_PIN_ROW7
+#define GPI_PIN_COL_BASE GPI_PIN_COL0
+#define GPI_PIN_COL_END GPI_PIN_COL9
+
+#define GPI_PIN_BASE GPI_PIN_ROW_BASE
+#define GPI_PIN_END GPI_PIN_COL_END
+
+#define ADP5588_GPIMAPSIZE_MAX (GPI_PIN_END - GPI_PIN_BASE + 1)
+
+struct adp5588_gpi_map {
+	unsigned short pin;
+	unsigned short sw_evt;
+};
+
 struct adp5588_kpad_platform_data {
 	int rows;			/* Number of rows */
 	int cols;			/* Number of columns */
@@ -87,6 +121,8 @@ struct adp5588_kpad_platform_data {
 	unsigned en_keylock:1;		/* Enable Key Lock feature */
 	unsigned short unlock_key1;	/* Unlock Key 1 */
 	unsigned short unlock_key2;	/* Unlock Key 2 */
+	const struct adp5588_gpi_map *gpimap;
+	unsigned short gpimapsize;
 };
 
 struct adp5588_gpio_platform_data {