From 2ba7eb1a5abad5659b6dfbb2ab0164dc9529212a Mon Sep 17 00:00:00 2001
From: "Kim, HeungJun" <riverful.kim@samsung.com>
Date: Mon, 15 Nov 2010 13:33:30 +0900
Subject: [PATCH] input: keyboard: mcs_touchkey: LED support

This commit adds support for LED found on this touchkey controller.

Signed-off-by: Sergey Larin <cerg2010cerg2010@mail.ru>
---
 drivers/input/keyboard/Kconfig        |  1 +
 drivers/input/keyboard/mcs_touchkey.c | 61 ++++++++++++++++++++++++---
 2 files changed, 57 insertions(+), 5 deletions(-)

diff --git a/drivers/input/keyboard/Kconfig b/drivers/input/keyboard/Kconfig
index 7c4f19dab34f..74c733dff9d6 100644
--- a/drivers/input/keyboard/Kconfig
+++ b/drivers/input/keyboard/Kconfig
@@ -409,6 +409,7 @@ config KEYBOARD_MAX7359
 config KEYBOARD_MCS
 	tristate "MELFAS MCS Touchkey"
 	depends on I2C
+	depends on LEDS_CLASS
 	help
 	  Say Y here if you have the MELFAS MCS5000/5080 touchkey controller
 	  chip in your system.
diff --git a/drivers/input/keyboard/mcs_touchkey.c b/drivers/input/keyboard/mcs_touchkey.c
index cd26a5560449..a0a168625c06 100644
--- a/drivers/input/keyboard/mcs_touchkey.c
+++ b/drivers/input/keyboard/mcs_touchkey.c
@@ -17,18 +17,26 @@
 #include <linux/pm.h>
 #include <linux/of_platform.h>
 #include <linux/of_gpio.h>
+#include <linux/workqueue.h>
+#include <linux/leds.h>
 
 /* MCS5000 Touchkey */
 #define MCS5000_TOUCHKEY_STATUS		0x04
 #define MCS5000_TOUCHKEY_STATUS_PRESS	7
 #define MCS5000_TOUCHKEY_FW		0x0a
 #define MCS5000_TOUCHKEY_BASE_VAL	0x61
+#define MCS5000_TOUCHKEY_LED_ON		0x1
+#define MCS5000_TOUCHKEY_LED_OFF	0x2
 
 /* MCS5080 Touchkey */
 #define MCS5080_TOUCHKEY_STATUS		0x00
 #define MCS5080_TOUCHKEY_STATUS_PRESS	3
 #define MCS5080_TOUCHKEY_FW		0x01
 #define MCS5080_TOUCHKEY_BASE_VAL	0x1
+#define MCS5080_TOUCHKEY_LED_ON		0x10
+#define MCS5080_TOUCHKEY_LED_OFF	0x20
+
+#define LED_TIME                       500
 
 enum mcs_touchkey_type {
 	MCS5000_TOUCHKEY,
@@ -40,6 +48,8 @@ struct mcs_touchkey_chip {
 	unsigned int pressbit;
 	unsigned int press_invert;
 	unsigned int baseval;
+	u8 led_on;
+	u8 led_off;
 };
 
 struct mcs_touchkey_data {
@@ -50,9 +60,25 @@ struct mcs_touchkey_data {
 	struct mcs_touchkey_chip chip;
 	unsigned int key_code;
 	unsigned int key_val;
+	struct led_classdev led_dev;
 	unsigned short keycodes[];
 };
 
+
+static void mcs_touchkey_led_brightness_set(struct led_classdev *led_dev,
+					    enum led_brightness brightness)
+{
+	struct mcs_touchkey_data *touchkey =
+		container_of(led_dev, struct mcs_touchkey_data, led_dev);
+	u8 buf;
+
+	if (brightness == LED_OFF)
+		buf = touchkey->chip.led_off;
+	else
+		buf = touchkey->chip.led_on;
+	i2c_master_send(touchkey->client, &buf, 1);
+}
+
 static irqreturn_t mcs_touchkey_interrupt(int irq, void *dev_id)
 {
 	struct mcs_touchkey_data *data = dev_id;
@@ -61,12 +87,21 @@ static irqreturn_t mcs_touchkey_interrupt(int irq, void *dev_id)
 	struct input_dev *input = data->input_dev;
 	unsigned int key_val;
 	unsigned int pressed;
-	int val;
+	u8 val;
+	int ret;
 
-	val = i2c_smbus_read_byte_data(client, chip->status_reg);
-	if (val < 0) {
-		dev_err(&client->dev, "i2c read error [%d]\n", val);
-		goto out;
+	if (chip->status_reg != 0) {
+		val = i2c_smbus_read_byte_data(client, chip->status_reg);
+		if (val < 0) {
+			dev_err(&client->dev, "i2c read error [%d]\n", val);
+			goto out;
+		}
+	} else {
+		ret = i2c_master_recv(client, &val, 1);
+		if (ret < 0) {
+			dev_err(&client->dev, "i2c read error [%d]\n", val);
+			goto out;
+		}
 	}
 
 	pressed = (val & (1 << chip->pressbit)) >> chip->pressbit;
@@ -187,12 +222,16 @@ static int mcs_touchkey_probe(struct i2c_client *client,
 		data->chip.status_reg = MCS5000_TOUCHKEY_STATUS;
 		data->chip.pressbit = MCS5000_TOUCHKEY_STATUS_PRESS;
 		data->chip.baseval = MCS5000_TOUCHKEY_BASE_VAL;
+		data->chip.led_on = MCS5000_TOUCHKEY_LED_ON;
+		data->chip.led_off = MCS5000_TOUCHKEY_LED_OFF;
 		fw_reg = MCS5000_TOUCHKEY_FW;
 	} else {
 		data->chip.status_reg = MCS5080_TOUCHKEY_STATUS;
 		data->chip.pressbit = MCS5080_TOUCHKEY_STATUS_PRESS;
 		data->chip.press_invert = 1;
 		data->chip.baseval = MCS5080_TOUCHKEY_BASE_VAL;
+		data->chip.led_on = MCS5080_TOUCHKEY_LED_ON;
+		data->chip.led_off = MCS5080_TOUCHKEY_LED_OFF;
 		fw_reg = MCS5080_TOUCHKEY_FW;
 	}
 
@@ -248,6 +287,18 @@ static int mcs_touchkey_probe(struct i2c_client *client,
 
 	i2c_set_clientdata(client, data);
 
+	data->led_dev.name = "mcs_touchkey_led";
+	data->led_dev.brightness = LED_FULL;
+	data->led_dev.max_brightness = LED_ON;
+	data->led_dev.brightness_set = mcs_touchkey_led_brightness_set;
+
+	error = devm_led_classdev_register(&client->dev, &data->led_dev);
+	if (error) {
+		dev_err(&client->dev,
+			"failed to register touchkey led: %d\n", error);
+		return error;
+	}
+
 	return 0;
 }
 
-- 
2.22.0