aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/input/keyboard/cypress/cypress-touchkey.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/input/keyboard/cypress/cypress-touchkey.c')
-rw-r--r--drivers/input/keyboard/cypress/cypress-touchkey.c1665
1 files changed, 1665 insertions, 0 deletions
diff --git a/drivers/input/keyboard/cypress/cypress-touchkey.c b/drivers/input/keyboard/cypress/cypress-touchkey.c
new file mode 100644
index 0000000..12d16dd
--- /dev/null
+++ b/drivers/input/keyboard/cypress/cypress-touchkey.c
@@ -0,0 +1,1665 @@
+/*
+ * Driver for keys on GPIO lines capable of generating interrupts.
+ *
+ * Copyright 2005 Phil Blundell
+ *
+ * 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/module.h>
+
+#include <linux/init.h>
+#include <linux/fs.h>
+#include <linux/i2c.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/sched.h>
+#include <linux/pm.h>
+#include <linux/sysctl.h>
+#include <linux/proc_fs.h>
+#include <linux/delay.h>
+#include <linux/platform_device.h>
+#include <linux/input.h>
+#include <mach/regs-gpio.h>
+#include <plat/gpio-cfg.h>
+#include <linux/gpio.h>
+#include <linux/miscdevice.h>
+#include <linux/uaccess.h>
+#include <linux/earlysuspend.h>
+#include <linux/io.h>
+#include <linux/regulator/consumer.h>
+#include <linux/regulator/driver.h>
+#include <linux/regulator/machine.h>
+#include <linux/regulator/consumer.h>
+#include <linux/regulator/driver.h>
+#include <linux/regulator/machine.h>
+
+#include "issp_extern.h"
+#ifdef CONFIG_TOUCHSCREEN_ATMEL_MXT540E
+#include <linux/i2c/mxt540e.h>
+#else
+#include <linux/i2c/mxt224_u1.h>
+#endif
+#include <linux/i2c/touchkey_i2c.h>
+
+/* M0 Touchkey temporary setting */
+
+#if defined(CONFIG_MACH_M0) || defined(CONFIG_MACH_C1VZW)
+#define CONFIG_MACH_Q1_BD
+#elif defined(CONFIG_MACH_C1) && !defined(CONFIG_TARGET_LOCALE_KOR)
+#define CONFIG_MACH_Q1_BD
+#elif defined(CONFIG_MACH_C1) && defined(CONFIG_TARGET_LOCALE_KOR)
+/* C1 KOR doesn't use Q1_BD */
+#endif
+
+#if defined(CONFIG_TARGET_LOCALE_NAATT_TEMP)
+/* Temp Fix NAGSM_SEL_ANDROID_MOHAMMAD_ANSARI_20111224*/
+#define CONFIG_TARGET_LOCALE_NAATT
+#endif
+
+#if defined(CONFIG_TARGET_LOCALE_NAATT)
+static int touchkey_keycode[5] = { 0,
+ KEY_MENU, KEY_ENTER, KEY_BACK, KEY_END };
+#elif defined(CONFIG_TARGET_LOCALE_NA)
+static int touchkey_keycode[5] = { NULL,
+ KEY_SEARCH, KEY_BACK, KEY_HOME, KEY_MENU };
+#elif defined(CONFIG_MACH_M0) \
+ || defined(CONFIG_MACH_C1) \
+ || defined(CONFIG_MACH_C1VZW)
+static int touchkey_keycode[3] = { 0, KEY_BACK, KEY_MENU,};
+#else
+static int touchkey_keycode[3] = { 0, KEY_MENU, KEY_BACK };
+#endif
+static const int touchkey_count = sizeof(touchkey_keycode) / sizeof(int);
+
+#if defined(TK_HAS_AUTOCAL)
+static u8 home_sensitivity;
+static u8 search_sensitivity;
+static u16 raw_data0;
+static u16 raw_data1;
+static u16 raw_data2;
+static u16 raw_data3;
+static u8 idac0;
+static u8 idac1;
+static u8 idac2;
+static u8 idac3;
+static u8 touchkey_threshold;
+
+static int touchkey_autocalibration(struct touchkey_i2c *tkey_i2c);
+#endif
+
+#if defined(CONFIG_TARGET_LOCALE_KOR)
+#ifndef TRUE
+#define TRUE 1
+#endif
+
+#ifndef FALSE
+#define FALSE 0
+#endif
+
+#if defined(SEC_TKEY_EVENT_DEBUG)
+static bool g_debug_tkey = TRUE;
+#else
+static bool g_debug_tkey = FALSE;
+#endif
+#endif
+
+static int touchkey_i2c_check(struct touchkey_i2c *tkey_i2c);
+
+static u8 menu_sensitivity;
+static u8 back_sensitivity;
+
+static int touchkey_enable;
+static bool touchkey_probe = true;
+
+static const struct i2c_device_id sec_touchkey_id[] = {
+ {"sec_touchkey", 0},
+ {}
+};
+
+MODULE_DEVICE_TABLE(i2c, sec_touchkey_id);
+
+extern int get_touchkey_firmware(char *version);
+static int touchkey_led_status;
+static int touchled_cmd_reversed;
+
+static int touchkey_debug_count;
+static char touchkey_debug[104];
+
+#ifdef LED_LDO_WITH_REGULATOR
+static void change_touch_key_led_voltage(int vol_mv)
+{
+ struct regulator *tled_regulator;
+
+ tled_regulator = regulator_get(NULL, "touch_led");
+ if (IS_ERR(tled_regulator)) {
+ pr_err("%s: failed to get resource %s\n", __func__,
+ "touch_led");
+ return;
+ }
+ regulator_set_voltage(tled_regulator, vol_mv * 1000, vol_mv * 1000);
+ regulator_put(tled_regulator);
+}
+
+static ssize_t brightness_control(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t size)
+{
+ int data;
+
+ if (sscanf(buf, "%d\n", &data) == 1) {
+ printk(KERN_ERR "[TouchKey] touch_led_brightness: %d\n", data);
+ change_touch_key_led_voltage(data);
+ } else {
+ printk(KERN_ERR "[TouchKey] touch_led_brightness Error\n");
+ }
+
+ return size;
+}
+#endif
+
+static void set_touchkey_debug(char value)
+{
+ if (touchkey_debug_count == 100)
+ touchkey_debug_count = 0;
+
+ touchkey_debug[touchkey_debug_count] = value;
+ touchkey_debug_count++;
+}
+
+static int i2c_touchkey_read(struct i2c_client *client,
+ u8 reg, u8 *val, unsigned int len)
+{
+ int err = 0;
+ int retry = 3;
+#if !defined(TK_USE_GENERAL_SMBUS)
+ struct i2c_msg msg[1];
+#endif
+
+ if ((client == NULL) || !(touchkey_enable == 1)
+ || !touchkey_probe) {
+ printk(KERN_ERR "[TouchKey] touchkey is not enabled. %d\n",
+ __LINE__);
+ return -ENODEV;
+ }
+
+ while (retry--) {
+#if defined(TK_USE_GENERAL_SMBUS)
+ err = i2c_smbus_read_i2c_block_data(client,
+ KEYCODE_REG, len, val);
+#else
+ msg->addr = client->addr;
+ msg->flags = I2C_M_RD;
+ msg->len = len;
+ msg->buf = val;
+ err = i2c_transfer(client->adapter, msg, 1);
+#endif
+
+ if (err >= 0)
+ return 0;
+ printk(KERN_ERR "[TouchKey] %s %d i2c transfer error\n",
+ __func__, __LINE__);
+ mdelay(10);
+ }
+ return err;
+
+}
+
+static int i2c_touchkey_write(struct i2c_client *client,
+ u8 *val, unsigned int len)
+{
+ int err = 0;
+ int retry = 3;
+#if !defined(TK_USE_GENERAL_SMBUS)
+ struct i2c_msg msg[1];
+#endif
+
+ if ((client == NULL) || !(touchkey_enable == 1)
+ || !touchkey_probe) {
+ printk(KERN_ERR "[TouchKey] touchkey is not enabled. %d\n",
+ __LINE__);
+ return -ENODEV;
+ }
+
+ while (retry--) {
+#if defined(TK_USE_GENERAL_SMBUS)
+ err = i2c_smbus_write_i2c_block_data(client,
+ KEYCODE_REG, len, val);
+#else
+ msg->addr = client->addr;
+ msg->flags = I2C_M_WR;
+ msg->len = len;
+ msg->buf = val;
+ err = i2c_transfer(client->adapter, msg, 1);
+#endif
+
+ if (err >= 0)
+ return 0;
+
+ printk(KERN_DEBUG "[TouchKey] %s %d i2c transfer error\n",
+ __func__, __LINE__);
+ mdelay(10);
+ }
+ return err;
+}
+
+#if defined(TK_HAS_AUTOCAL)
+static int touchkey_autocalibration(struct touchkey_i2c *tkey_i2c)
+{
+ u8 data[6] = { 0, };
+ int count = 0;
+ int ret = 0;
+ unsigned short retry = 0;
+
+#if defined(CONFIG_TARGET_LOCALE_NA)
+ if (tkey_i2c->module_ver < 8)
+ return -1;
+#endif
+
+ while (retry < 3) {
+ ret = i2c_touchkey_read(tkey_i2c->client, KEYCODE_REG, data, 4);
+ if (ret < 0) {
+ printk(KERN_ERR "[TouchKey]i2c read fail.\n");
+ return ret;
+ }
+ printk(KERN_DEBUG
+ "[TouchKey] data[0]=%x data[1]=%x data[2]=%x data[3]=%x\n",
+ data[0], data[1], data[2], data[3]);
+
+ /* Send autocal Command */
+ data[0] = 0x50;
+ data[3] = 0x01;
+
+ count = i2c_touchkey_write(tkey_i2c->client, data, 4);
+
+ msleep(100);
+
+ /* Check autocal status */
+ ret = i2c_touchkey_read(tkey_i2c->client, KEYCODE_REG, data, 6);
+
+ if ((data[5] & TK_BIT_AUTOCAL)) {
+ printk(KERN_DEBUG "[Touchkey] autocal Enabled\n");
+ break;
+ } else
+ printk(KERN_DEBUG
+ "[Touchkey] autocal disabled, retry %d\n",
+ retry);
+
+ retry = retry + 1;
+ }
+
+ if (retry == 3)
+ printk(KERN_DEBUG "[Touchkey] autocal failed\n");
+
+ return count;
+}
+#endif
+
+#ifdef CONFIG_TARGET_LOCALE_NAATT
+static ssize_t set_touchkey_autocal_testmode(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t size)
+{
+ struct touchkey_i2c *tkey_i2c = dev_get_drvdata(dev);
+ int count = 0;
+ u8 set_data;
+ int on_off;
+
+ if (sscanf(buf, "%d\n", &on_off) == 1) {
+ printk(KERN_ERR "[TouchKey] Test Mode : %d\n", on_off);
+
+ if (on_off == 1) {
+ set_data = 0x40;
+ count = i2c_touchkey_write(tkey_i2c->client,
+ &set_data, 1);
+ } else {
+ tkey_i2c->pdata->power_on(0);
+ msleep(50);
+ tkey_i2c->pdata->power_on(1);
+ msleep(50);
+#if defined(TK_HAS_AUTOCAL)
+ touchkey_autocalibration();
+#endif
+ }
+ } else {
+ printk(KERN_ERR "[TouchKey] touch_led_brightness Error\n");
+ }
+
+ return count;
+}
+#endif
+
+#if defined(TK_HAS_AUTOCAL)
+static ssize_t touchkey_raw_data0_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct touchkey_i2c *tkey_i2c = dev_get_drvdata(dev);
+ u8 data[26] = { 0, };
+ int ret;
+
+ printk(KERN_DEBUG "called %s\n", __func__);
+ ret = i2c_touchkey_read(tkey_i2c->client, KEYCODE_REG, data, 26);
+#if defined(CONFIG_TARGET_LOCALE_NA)
+ printk(KERN_DEBUG "called %s data[18] =%d,data[19] = %d\n", __func__,
+ data[18], data[19]);
+ raw_data0 = ((0x00FF & data[18]) << 8) | data[19];
+#elif defined(CONFIG_MACH_M0) || defined(CONFIG_MACH_C1)\
+|| defined(CONFIG_MACH_C1VZW)
+ printk(KERN_DEBUG "called %s data[16] =%d,data[17] = %d\n", __func__,
+ data[16], data[17]);
+ raw_data0 = ((0x00FF & data[16]) << 8) | data[17]; /* menu*/
+#elif defined(CONFIG_MACH_Q1_BD)
+ printk(KERN_DEBUG "called %s data[16] =%d,data[17] = %d\n", __func__,
+ data[16], data[17]);
+ raw_data0 = ((0x00FF & data[14]) << 8) | data[15];
+#else
+ printk(KERN_DEBUG "called %s data[18] =%d,data[19] = %d\n", __func__,
+ data[10], data[11]);
+ raw_data0 = ((0x00FF & data[10]) << 8) | data[11];
+#endif
+ return sprintf(buf, "%d\n", raw_data0);
+}
+
+static ssize_t touchkey_raw_data1_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct touchkey_i2c *tkey_i2c = dev_get_drvdata(dev);
+ u8 data[26] = { 0, };
+ int ret;
+
+ printk(KERN_DEBUG "called %s\n", __func__);
+ ret = i2c_touchkey_read(tkey_i2c->client, KEYCODE_REG, data, 26);
+#if defined(CONFIG_TARGET_LOCALE_NA)
+ printk(KERN_DEBUG "called %s data[20] =%d,data[21] = %d\n", __func__,
+ data[20], data[21]);
+ raw_data1 = ((0x00FF & data[20]) << 8) | data[21];
+#elif defined(CONFIG_MACH_M0) || defined(CONFIG_MACH_C1)\
+|| defined(CONFIG_MACH_C1VZW)
+ printk(KERN_DEBUG "called %s data[14] =%d,data[15] = %d\n", __func__,
+ data[14], data[15]);
+ raw_data1 = ((0x00FF & data[14]) << 8) | data[15]; /*back*/
+#elif defined(CONFIG_MACH_Q1_BD)
+ printk(KERN_DEBUG "called %s data[14] =%d,data[15] = %d\n", __func__,
+ data[14], data[15]);
+ raw_data1 = ((0x00FF & data[16]) << 8) | data[17];
+#else
+ printk(KERN_DEBUG "called %s data[20] =%d,data[21] = %d\n", __func__,
+ data[12], data[13]);
+ raw_data1 = ((0x00FF & data[12]) << 8) | data[13];
+#endif /* CONFIG_TARGET_LOCALE_NA */
+ return sprintf(buf, "%d\n", raw_data1);
+}
+
+static ssize_t touchkey_raw_data2_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct touchkey_i2c *tkey_i2c = dev_get_drvdata(dev);
+ u8 data[26] = { 0, };
+ int ret;
+
+ printk(KERN_DEBUG "called %s\n", __func__);
+ ret = i2c_touchkey_read(tkey_i2c->client, KEYCODE_REG, data, 26);
+#if defined(CONFIG_TARGET_LOCALE_NA)
+ printk(KERN_DEBUG "called %s data[22] =%d,data[23] = %d\n", __func__,
+ data[22], data[23]);
+ raw_data2 = ((0x00FF & data[22]) << 8) | data[23];
+#else
+ printk(KERN_DEBUG "called %s data[22] =%d,data[23] = %d\n", __func__,
+ data[14], data[15]);
+ raw_data2 = ((0x00FF & data[14]) << 8) | data[15];
+#endif /* CONFIG_TARGET_LOCALE_NA */
+ return sprintf(buf, "%d\n", raw_data2);
+}
+
+static ssize_t touchkey_raw_data3_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct touchkey_i2c *tkey_i2c = dev_get_drvdata(dev);
+ u8 data[26] = { 0, };
+ int ret;
+
+ printk(KERN_DEBUG "called %s\n", __func__);
+ ret = i2c_touchkey_read(tkey_i2c->client, KEYCODE_REG, data, 26);
+#if defined(CONFIG_TARGET_LOCALE_NA)
+ printk(KERN_DEBUG "called %s data[24] =%d,data[25] = %d\n", __func__,
+ data[24], data[25]);
+ raw_data3 = ((0x00FF & data[24]) << 8) | data[25];
+#else
+ printk(KERN_DEBUG "called %s data[24] =%d,data[25] = %d\n", __func__,
+ data[16], data[17]);
+ raw_data3 = ((0x00FF & data[16]) << 8) | data[17];
+#endif /* CONFIG_TARGET_LOCALE_NA */
+ return sprintf(buf, "%d\n", raw_data3);
+}
+
+static ssize_t touchkey_idac0_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct touchkey_i2c *tkey_i2c = dev_get_drvdata(dev);
+ u8 data[10];
+ int ret;
+#ifdef CONFIG_TARGET_LOCALE_NA
+ if (tkey_i2c->module_ver < 8)
+ return 0;
+#endif
+
+ printk(KERN_DEBUG "called %s\n", __func__);
+ ret = i2c_touchkey_read(tkey_i2c->client, KEYCODE_REG, data, 10);
+ printk(KERN_DEBUG "called %s data[6] =%d\n", __func__, data[6]);
+ idac0 = data[6];
+ return sprintf(buf, "%d\n", idac0);
+}
+
+static ssize_t touchkey_idac1_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct touchkey_i2c *tkey_i2c = dev_get_drvdata(dev);
+ u8 data[10];
+ int ret;
+#ifdef CONFIG_TARGET_LOCALE_NA
+ if (tkey_i2c->module_ver < 8)
+ return 0;
+#endif
+
+ printk(KERN_DEBUG "called %s\n", __func__);
+ ret = i2c_touchkey_read(tkey_i2c->client, KEYCODE_REG, data, 10);
+ printk(KERN_DEBUG "called %s data[7] = %d\n", __func__, data[7]);
+ idac1 = data[7];
+ return sprintf(buf, "%d\n", idac1);
+}
+
+static ssize_t touchkey_idac2_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct touchkey_i2c *tkey_i2c = dev_get_drvdata(dev);
+ u8 data[10];
+ int ret;
+#ifdef CONFIG_TARGET_LOCALE_NA
+ if (tkey_i2c->module_ver < 8)
+ return 0;
+#endif
+
+ printk(KERN_DEBUG "called %s\n", __func__);
+ ret = i2c_touchkey_read(tkey_i2c->client, KEYCODE_REG, data, 10);
+ printk(KERN_DEBUG "called %s data[8] =%d\n", __func__, data[8]);
+ idac2 = data[8];
+ return sprintf(buf, "%d\n", idac2);
+}
+
+static ssize_t touchkey_idac3_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct touchkey_i2c *tkey_i2c = dev_get_drvdata(dev);
+ u8 data[10];
+ int ret;
+#ifdef CONFIG_TARGET_LOCALE_NA
+ if (tkey_i2c->module_ver < 8)
+ return 0;
+#endif
+
+ printk(KERN_DEBUG "called %s\n", __func__);
+ ret = i2c_touchkey_read(tkey_i2c->client, KEYCODE_REG, data, 10);
+ printk(KERN_DEBUG "called %s data[9] = %d\n", __func__, data[9]);
+ idac3 = data[9];
+ return sprintf(buf, "%d\n", idac3);
+}
+
+static ssize_t touchkey_threshold_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct touchkey_i2c *tkey_i2c = dev_get_drvdata(dev);
+ u8 data[10];
+ int ret;
+
+ printk(KERN_DEBUG "called %s\n", __func__);
+ ret = i2c_touchkey_read(tkey_i2c->client, KEYCODE_REG, data, 10);
+ printk(KERN_DEBUG "called %s data[4] = %d\n", __func__, data[4]);
+ touchkey_threshold = data[4];
+ return sprintf(buf, "%d\n", touchkey_threshold);
+}
+#endif
+
+#if defined(TK_HAS_FIRMWARE_UPDATE)
+static int touchkey_firmware_update(struct touchkey_i2c *tkey_i2c)
+{
+ int retry = 3;
+ int ret = 0;
+ char data[3];
+
+ disable_irq(tkey_i2c->irq);
+
+
+ ret = i2c_touchkey_read(tkey_i2c->client, KEYCODE_REG, data, 3);
+ if (ret < 0) {
+ printk(KERN_DEBUG
+ "[TouchKey] i2c read fail. do not excute firm update.\n");
+ data[1] = 0;
+ data[2] = 0;
+ }
+
+ printk(KERN_ERR "%s F/W version: 0x%x, Module version:0x%x\n", __func__,
+ data[1], data[2]);
+
+ tkey_i2c->firmware_ver = data[1];
+ tkey_i2c->module_ver = data[2];
+
+
+#if defined(CONFIG_MACH_M0) || defined(CONFIG_MACH_C1) \
+|| defined(CONFIG_MACH_C1VZW)
+ if ((tkey_i2c->firmware_ver < TK_FIRMWARE_VER) &&
+ (tkey_i2c->module_ver <= TK_MODULE_VER)) {
+#else
+ if ((tkey_i2c->firmware_ver < TK_FIRMWARE_VER) &&
+ (tkey_i2c->module_ver == TK_MODULE_VER)) {
+#endif
+ printk(KERN_DEBUG "[TouchKey] firmware auto update excute\n");
+
+ tkey_i2c->update_status = TK_UPDATE_DOWN;
+
+ while (retry--) {
+ if (ISSP_main(tkey_i2c) == 0) {
+ printk(KERN_DEBUG
+ "[TouchKey]firmware update succeeded\n");
+ tkey_i2c->update_status = TK_UPDATE_PASS;
+ msleep(50);
+ break;
+ }
+ msleep(50);
+ printk(KERN_DEBUG
+ "[TouchKey] firmware update failed. retry\n");
+ }
+ if (retry <= 0) {
+ tkey_i2c->pdata->power_on(0);
+ tkey_i2c->update_status = TK_UPDATE_FAIL;
+ printk(KERN_DEBUG
+ "[TouchKey] firmware update failed.\n");
+ }
+ ret = touchkey_i2c_check(tkey_i2c);
+ if (ret < 0) {
+ printk(KERN_DEBUG
+ "[TouchKey] i2c read fail.\n");
+ return TK_UPDATE_FAIL;
+ }
+
+ printk(KERN_DEBUG "[TouchKey] firm ver = %d, module ver = %d\n",
+ tkey_i2c->firmware_ver, tkey_i2c->module_ver);
+ } else {
+ printk(KERN_DEBUG
+ "[TouchKey] firmware auto update do not excute\n");
+ printk(KERN_DEBUG
+ "[TouchKey] firmware_ver(banary=%d, current=%d)\n",
+ TK_FIRMWARE_VER, tkey_i2c->firmware_ver);
+ printk(KERN_DEBUG
+ "[TouchKey] module_ver(banary=%d, current=%d)\n",
+ TK_MODULE_VER, tkey_i2c->module_ver);
+ }
+ enable_irq(tkey_i2c->irq);
+ return TK_UPDATE_PASS;
+}
+#else
+static int touchkey_firmware_update(struct touchkey_i2c *tkey_i2c)
+{
+ char data[3];
+ int retry;
+ int ret = 0;
+
+ ret = i2c_touchkey_read(tkey_i2c->client, KEYCODE_REG, data, 3);
+ if (ret < 0) {
+ printk(KERN_DEBUG
+ "[TouchKey] i2c read fail. do not excute firm update.\n");
+ return ret;
+ }
+
+ printk(KERN_ERR "%s F/W version: 0x%x, Module version:0x%x\n", __func__,
+ data[1], data[2]);
+ retry = 3;
+
+ tkey_i2c->firmware_ver = data[1];
+ tkey_i2c->module_ver = data[2];
+
+ if (tkey_i2c->firmware_ver < 0x0A) {
+ tkey_i2c->update_status = TK_UPDATE_DOWN;
+ while (retry--) {
+ if (ISSP_main(tkey_i2c) == 0) {
+ printk(KERN_ERR
+ "[TOUCHKEY]Touchkey_update succeeded\n");
+ tkey_i2c->update_status = TK_UPDATE_PASS;
+ break;
+ }
+ printk(KERN_ERR "touchkey_update failed...retry...\n");
+ }
+ if (retry <= 0) {
+ tkey_i2c->pdata->power_on(0);
+ tkey_i2c->update_status = TK_UPDATE_FAIL;
+ }
+ } else {
+ if (tkey_i2c->firmware_ver >= 0x0A) {
+ printk(KERN_ERR
+ "[TouchKey] Not F/W update. Cypess touch-key F/W version is latest\n");
+ } else {
+ printk(KERN_ERR
+ "[TouchKey] Not F/W update. Cypess touch-key version(module or F/W) is not valid\n");
+ }
+ }
+ return ret;
+}
+#endif
+
+#ifndef TEST_JIG_MODE
+static irqreturn_t touchkey_interrupt(int irq, void *dev_id)
+{
+ struct touchkey_i2c *tkey_i2c = dev_id;
+ u8 data[3];
+ int ret;
+ int retry = 10;
+ int keycode_type = 0;
+ int pressed;
+
+ set_touchkey_debug('a');
+
+ retry = 3;
+ while (retry--) {
+ ret = i2c_touchkey_read(tkey_i2c->client, KEYCODE_REG, data, 3);
+ if (!ret)
+ break;
+ else {
+ printk(KERN_DEBUG
+ "[TouchKey] i2c read failed, ret:%d, retry: %d\n",
+ ret, retry);
+ continue;
+ }
+ }
+ if (ret < 0)
+ return IRQ_HANDLED;
+
+ set_touchkey_debug(data[0]);
+
+ keycode_type = (data[0] & TK_BIT_KEYCODE);
+ pressed = !(data[0] & TK_BIT_PRESS_EV);
+
+ if (keycode_type <= 0 || keycode_type >= touchkey_count) {
+ printk(KERN_DEBUG "[Touchkey] keycode_type err\n");
+ return IRQ_HANDLED;
+ }
+
+ if (pressed)
+ set_touchkey_debug('P');
+
+ if (get_tsp_status() && pressed)
+ printk(KERN_DEBUG "[TouchKey] touchkey pressed but don't send event because touch is pressed.\n");
+ else {
+ input_report_key(tkey_i2c->input_dev,
+ touchkey_keycode[keycode_type], pressed);
+ input_sync(tkey_i2c->input_dev);
+ /* printk(KERN_DEBUG "[TouchKey] keycode:%d pressed:%d\n",
+ touchkey_keycode[keycode_index], pressed); */
+
+ #if defined(CONFIG_TARGET_LOCALE_KOR)
+ if (g_debug_tkey == true) {
+ printk(KERN_DEBUG "[TouchKey] keycode[%d]=%d pressed:%d\n",
+ keycode_type, touchkey_keycode[keycode_type], pressed);
+ } else {
+ printk(KERN_DEBUG "[TouchKey] pressed:%d\n", pressed);
+ }
+ #endif
+ }
+ set_touchkey_debug('A');
+ return IRQ_HANDLED;
+}
+#else
+static irqreturn_t touchkey_interrupt(int irq, void *dev_id)
+{
+ struct touchkey_i2c *tkey_i2c = dev_id;
+ u8 data[18];
+ int ret;
+ int retry = 10;
+ int keycode_type = 0;
+ int pressed;
+
+#if 0
+ if (gpio_get_value(_3_GPIO_TOUCH_INT)) {
+ printk(KERN_DEBUG "[TouchKey] Unknown state.\n", __func__);
+ return IRQ_HANDLED;
+ }
+#endif
+
+ set_touchkey_debug('a');
+
+#ifdef CONFIG_CPU_FREQ
+ /* set_dvfs_target_level(LEV_800MHZ); */
+#endif
+
+ retry = 3;
+ while (retry--) {
+#if defined(CONFIG_TARGET_LOCALE_NA) || defined(CONFIG_MACH_Q1_BD)\
+ || defined(CONFIG_MACH_C1)
+ ret = i2c_touchkey_read(tkey_i2c->client,
+ KEYCODE_REG, data, 18);
+#else
+ ret = i2c_touchkey_read(tkey_i2c->client,
+ KEYCODE_REG, data, 10);
+#endif
+ if (!ret)
+ break;
+ else {
+ printk(KERN_DEBUG
+ "[TouchKey] i2c read failed, ret:%d, retry: %d\n",
+ ret, retry);
+ continue;
+ }
+ }
+ if (ret < 0)
+ return IRQ_HANDLED;
+
+#if defined(CONFIG_TARGET_LOCALE_NA)
+#if defined(CONFIG_MACH_C1_NA_SPR_EPIC2_REV00)
+ menu_sensitivity = data[11];
+ home_sensitivity = data[13];
+ search_sensitivity = data[15];
+ back_sensitivity = data[17];
+#else
+ if (tkey_i2c->module_ver >= 8) {
+ menu_sensitivity = data[17];
+ home_sensitivity = data[15];
+ search_sensitivity = data[11];
+ back_sensitivity = data[13];
+ } else {
+ menu_sensitivity = data[6];
+ home_sensitivity = data[7];
+ search_sensitivity = data[8];
+ back_sensitivity = data[9];
+ }
+#endif
+#elif defined(CONFIG_MACH_Q1_BD) || defined(CONFIG_MACH_C1)
+ menu_sensitivity = data[13];
+ back_sensitivity = data[11];
+#else
+ menu_sensitivity = data[7];
+ back_sensitivity = data[9];
+#endif /* CONFIG_TARGET_LOCALE_NA */
+
+ set_touchkey_debug(data[0]);
+
+ keycode_type = (data[0] & TK_BIT_KEYCODE);
+ pressed = !(data[0] & TK_BIT_PRESS_EV);
+
+ if (keycode_type <= 0 || keycode_type >= touchkey_count) {
+ printk(KERN_DEBUG "[Touchkey] keycode_type err\n");
+ return IRQ_HANDLED;
+ }
+
+ if (pressed)
+ set_touchkey_debug('P');
+
+ if (get_tsp_status() && pressed)
+ printk(KERN_DEBUG "[TouchKey] touchkey pressed"
+ " but don't send event because touch is pressed.\n");
+ else {
+ input_report_key(touchkey_driver->input_dev,
+ touchkey_keycode[keycode_type], pressed);
+ input_sync(touchkey_driver->input_dev);
+ /* printk(KERN_DEBUG "[TouchKey] keycode:%d pressed:%d\n",
+ touchkey_keycode[keycode_index], pressed); */
+ }
+
+ if (keycode_type == 1)
+ printk(KERN_DEBUG "search key sensitivity = %d\n",
+ search_sensitivity);
+ if (keycode_type == 2)
+ printk(KERN_DEBUG "back key sensitivity = %d\n",
+ back_sensitivity);
+#ifdef CONFIG_TARGET_LOCALE_NA
+ if (keycode_type == 3)
+ printk(KERN_DEBUG "home key sensitivity = %d\n",
+ home_sensitivity);
+ if (keycode_type == 4)
+ printk(KERN_DEBUG "menu key sensitivity = %d\n",
+ menu_sensitivity);
+#endif
+
+ set_touchkey_debug('A');
+ return IRQ_HANDLED;
+}
+#endif
+
+#ifdef CONFIG_HAS_EARLYSUSPEND
+static int sec_touchkey_early_suspend(struct early_suspend *h)
+{
+ struct touchkey_i2c *tkey_i2c =
+ container_of(h, struct touchkey_i2c, early_suspend);
+ int ret;
+ int i;
+
+ disable_irq(tkey_i2c->irq);
+ ret = cancel_work_sync(&tkey_i2c->update_work);
+ if (ret) {
+ printk(KERN_DEBUG "[Touchkey] enable_irq ret=%d\n", ret);
+ enable_irq(tkey_i2c->irq);
+ }
+
+ /* release keys */
+ for (i = 1; i < touchkey_count; ++i) {
+ input_report_key(tkey_i2c->input_dev,
+ touchkey_keycode[i], 0);
+ }
+ input_sync(tkey_i2c->input_dev);
+
+ touchkey_enable = 0;
+ set_touchkey_debug('S');
+ printk(KERN_DEBUG "[TouchKey] sec_touchkey_early_suspend\n");
+ if (touchkey_enable < 0) {
+ printk(KERN_DEBUG "[TouchKey] ---%s---touchkey_enable: %d\n",
+ __func__, touchkey_enable);
+ return 0;
+ }
+
+ /* disable ldo18 */
+ tkey_i2c->pdata->led_power_on(0);
+
+ /* disable ldo11 */
+ tkey_i2c->pdata->power_on(0);
+
+ return 0;
+}
+
+static int sec_touchkey_late_resume(struct early_suspend *h)
+{
+ struct touchkey_i2c *tkey_i2c =
+ container_of(h, struct touchkey_i2c, early_suspend);
+#ifdef TEST_JIG_MODE
+ unsigned char get_touch = 0x40;
+#endif
+
+ set_touchkey_debug('R');
+ printk(KERN_DEBUG "[TouchKey] sec_touchkey_late_resume\n");
+
+ /* enable ldo11 */
+ tkey_i2c->pdata->power_on(1);
+
+ if (touchkey_enable < 0) {
+ printk(KERN_DEBUG "[TouchKey] ---%s---touchkey_enable: %d\n",
+ __func__, touchkey_enable);
+ return 0;
+ }
+ msleep(50);
+ tkey_i2c->pdata->led_power_on(1);
+
+ touchkey_enable = 1;
+
+#if defined(TK_HAS_AUTOCAL)
+ touchkey_autocalibration(tkey_i2c);
+#endif
+
+ if (touchled_cmd_reversed) {
+ touchled_cmd_reversed = 0;
+ i2c_touchkey_write(tkey_i2c->client,
+ (u8 *) &touchkey_led_status, 1);
+ printk(KERN_DEBUG "[Touchkey] LED returned on\n");
+ }
+#ifdef TEST_JIG_MODE
+ i2c_touchkey_write(tkey_i2c->client, &get_touch, 1);
+#endif
+
+ enable_irq(tkey_i2c->irq);
+
+ return 0;
+}
+#endif
+
+static int touchkey_i2c_check(struct touchkey_i2c *tkey_i2c)
+{
+ char data[3] = { 0, };
+ int ret = 0;
+
+ ret = i2c_touchkey_read(tkey_i2c->client, KEYCODE_REG, data, 3);
+ if (ret < 0) {
+ printk(KERN_ERR "[TouchKey] module version read fail\n");
+ return ret;
+ }
+
+ tkey_i2c->firmware_ver = data[1];
+ tkey_i2c->module_ver = data[2];
+
+ return ret;
+}
+
+ssize_t touchkey_update_read(struct file *filp, char *buf, size_t count,
+ loff_t *f_pos)
+{
+ char data[3] = { 0, };
+
+ get_touchkey_firmware(data);
+ put_user(data[1], buf);
+
+ return 1;
+}
+
+static ssize_t touch_version_read(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct touchkey_i2c *tkey_i2c = dev_get_drvdata(dev);
+ char data[3] = { 0, };
+ int count;
+
+ i2c_touchkey_read(tkey_i2c->client, KEYCODE_REG, data, 3);
+
+ count = sprintf(buf, "0x%x\n", data[1]);
+
+ printk(KERN_DEBUG "[TouchKey] touch_version_read 0x%x\n", data[1]);
+ printk(KERN_DEBUG "[TouchKey] module_version_read 0x%x\n", data[2]);
+
+ return count;
+}
+
+static ssize_t touch_version_write(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t size)
+{
+ printk(KERN_DEBUG "[TouchKey] input data --> %s\n", buf);
+
+ return size;
+}
+
+void touchkey_update_func(struct work_struct *work)
+{
+ struct touchkey_i2c *tkey_i2c =
+ container_of(work, struct touchkey_i2c, update_work);
+ int retry = 3;
+#if defined(CONFIG_TARGET_LOCALE_NAATT)
+ char data[3];
+ i2c_touchkey_read(tkey_i2c->client, KEYCODE_REG, data, 3);
+ printk(KERN_DEBUG "[%s] F/W version: 0x%x, Module version:0x%x\n",
+ __func__, data[1], data[2]);
+#endif
+ tkey_i2c->update_status = TK_UPDATE_DOWN;
+ printk(KERN_DEBUG "[TouchKey] %s start\n", __func__);
+ touchkey_enable = 0;
+ while (retry--) {
+ if (ISSP_main(tkey_i2c) == 0) {
+ printk(KERN_DEBUG
+ "[TouchKey] touchkey_update succeeded\n");
+ msleep(50);
+ touchkey_enable = 1;
+#if defined(TK_HAS_AUTOCAL)
+ touchkey_autocalibration(tkey_i2c);
+#endif
+ tkey_i2c->update_status = TK_UPDATE_PASS;
+ enable_irq(tkey_i2c->irq);
+ return;
+ }
+ tkey_i2c->pdata->power_on(0);
+ }
+ enable_irq(tkey_i2c->irq);
+ tkey_i2c->update_status = TK_UPDATE_FAIL;
+ printk(KERN_DEBUG "[TouchKey] touchkey_update failed\n");
+ return;
+}
+
+static ssize_t touch_update_write(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t size)
+{
+ struct touchkey_i2c *tkey_i2c = dev_get_drvdata(dev);
+#ifdef CONFIG_TARGET_LOCALE_NA
+ if (tkey_i2c->module_ver < 8) {
+ printk(KERN_DEBUG
+ "[TouchKey] Skipping f/w update : module_version =%d\n",
+ tkey_i2c->module_ver);
+ tkey_i2c->update_status = TK_UPDATE_PASS;
+ return 1;
+ } else {
+#endif /* CONFIG_TARGET_LOCALE_NA */
+ printk(KERN_DEBUG "[TouchKey] touchkey firmware update\n");
+
+ if (*buf == 'S') {
+ disable_irq(tkey_i2c->irq);
+ schedule_work(&tkey_i2c->update_work);
+ }
+ return size;
+#ifdef CONFIG_TARGET_LOCALE_NA
+ }
+#endif /* CONFIG_TARGET_LOCALE_NA */
+}
+
+static ssize_t touch_update_read(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct touchkey_i2c *tkey_i2c = dev_get_drvdata(dev);
+ int count = 0;
+
+ printk(KERN_DEBUG
+ "[TouchKey] touch_update_read: update_status %d\n",
+ tkey_i2c->update_status);
+
+ if (tkey_i2c->update_status == TK_UPDATE_PASS)
+ count = sprintf(buf, "PASS\n");
+ else if (tkey_i2c->update_status == TK_UPDATE_DOWN)
+ count = sprintf(buf, "Downloading\n");
+ else if (tkey_i2c->update_status == TK_UPDATE_FAIL)
+ count = sprintf(buf, "Fail\n");
+
+ return count;
+}
+
+static ssize_t touchkey_led_control(struct device *dev,
+ struct device_attribute *attr, const char *buf,
+ size_t size)
+{
+ struct touchkey_i2c *tkey_i2c = dev_get_drvdata(dev);
+ int data;
+ int ret;
+ static const int ledCmd[] = {TK_CMD_LED_ON, TK_CMD_LED_OFF};
+
+ ret = sscanf(buf, "%d", &data);
+ if (ret != 1) {
+ printk(KERN_DEBUG "[TouchKey] %s, %d err\n",
+ __func__, __LINE__);
+ return size;
+ }
+
+ if (data != 1 && data != 2) {
+ printk(KERN_DEBUG "[TouchKey] %s wrong cmd %x\n",
+ __func__, data);
+ return size;
+ }
+
+#if defined(CONFIG_TARGET_LOCALE_NA)
+ if (tkey_i2c->module_ver >= 8)
+ data = ledCmd[data-1];
+#else
+ data = ledCmd[data-1];
+#endif
+
+ ret = i2c_touchkey_write(tkey_i2c->client, (u8 *) &data, 1);
+
+ if (ret == -ENODEV) {
+ printk(KERN_DEBUG"[Touchkey] error to write i2c\n");
+ touchled_cmd_reversed = 1;
+ }
+
+ touchkey_led_status = data;
+
+ return size;
+}
+
+#if defined(CONFIG_TARGET_LOCALE_NAATT) || defined(CONFIG_TARGET_LOCALE_NA)
+static ssize_t touchkey_menu_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct touchkey_i2c *tkey_i2c = dev_get_drvdata(dev);
+ u8 data[18] = { 0, };
+ int ret;
+
+ printk(KERN_DEBUG "called %s\n", __func__);
+ ret = i2c_touchkey_read(tkey_i2c->client, KEYCODE_REG, data, 18);
+#ifdef CONFIG_TARGET_LOCALE_NA
+ if (tkey_i2c->module_ver < 8) {
+ printk(KERN_DEBUG "called %s data[12] =%d,data[13] = %d\n",
+ __func__, data[12], data[13]);
+ menu_sensitivity = ((0x00FF & data[12]) << 8) | data[13];
+ } else {
+ printk(KERN_DEBUG "called %s data[17] =%d\n", __func__,
+ data[17]);
+ menu_sensitivity = data[17];
+ }
+#else
+ printk(KERN_DEBUG "called %s data[10] =%d,data[11] = %d\n", __func__,
+ data[10], data[11]);
+ menu_sensitivity = ((0x00FF & data[10]) << 8) | data[11];
+#endif /* CONFIG_TARGET_LOCALE_NA */
+ return sprintf(buf, "%d\n", menu_sensitivity);
+}
+
+static ssize_t touchkey_home_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct touchkey_i2c *tkey_i2c = dev_get_drvdata(dev);
+ u8 data[18] = { 0, };
+ int ret;
+
+ printk(KERN_DEBUG "called %s\n", __func__);
+ ret = i2c_touchkey_read(tkey_i2c->client, KEYCODE_REG, data, 18);
+#ifdef CONFIG_TARGET_LOCALE_NA
+ if (tkey_i2c->module_ver < 8) {
+ printk(KERN_DEBUG "called %s data[10] =%d,data[11] = %d\n",
+ __func__, data[10], data[11]);
+ home_sensitivity = ((0x00FF & data[10]) << 8) | data[11];
+ } else {
+ printk(KERN_DEBUG "called %s data[15] =%d\n", __func__,
+ data[15]);
+ home_sensitivity = data[15];
+ }
+#else
+ printk(KERN_DEBUG "called %s data[12] =%d,data[13] = %d\n", __func__,
+ data[12], data[13]);
+ home_sensitivity = ((0x00FF & data[12]) << 8) | data[13];
+#endif /* CONFIG_TARGET_LOCALE_NA */
+ return sprintf(buf, "%d\n", home_sensitivity);
+}
+
+static ssize_t touchkey_back_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct touchkey_i2c *tkey_i2c = dev_get_drvdata(dev);
+ u8 data[18] = { 0, };
+ int ret;
+
+ printk(KERN_DEBUG "called %s\n", __func__);
+ ret = i2c_touchkey_read(tkey_i2c->client, KEYCODE_REG, data, 18);
+#ifdef CONFIG_TARGET_LOCALE_NA
+ if (tkey_i2c->module_ver < 8) {
+ printk(KERN_DEBUG "called %s data[8] =%d,data[9] = %d\n",
+ __func__, data[8], data[9]);
+ back_sensitivity = ((0x00FF & data[8]) << 8) | data[9];
+ } else {
+ printk(KERN_DEBUG "called %s data[13] =%d\n", __func__,
+ data[13]);
+ back_sensitivity = data[13];
+ }
+#else
+ printk(KERN_DEBUG "called %s data[14] =%d,data[15] = %d\n", __func__,
+ data[14], data[15]);
+ back_sensitivity = ((0x00FF & data[14]) << 8) | data[15];
+#endif /* CONFIG_TARGET_LOCALE_NA */
+ return sprintf(buf, "%d\n", back_sensitivity);
+}
+
+static ssize_t touchkey_search_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct touchkey_i2c *tkey_i2c = dev_get_drvdata(dev);
+ u8 data[18] = { 0, };
+ int ret;
+
+ printk(KERN_DEBUG "called %s\n", __func__);
+ ret = i2c_touchkey_read(tkey_i2c->client, KEYCODE_REG, data, 18);
+#ifdef CONFIG_TARGET_LOCALE_NA
+ if (tkey_i2c->module_ver < 8) {
+ printk(KERN_DEBUG "called %s data[6] =%d,data[7] = %d\n",
+ __func__, data[6], data[7]);
+ search_sensitivity = ((0x00FF & data[6]) << 8) | data[7];
+ } else {
+ printk(KERN_DEBUG "called %s data[11] =%d\n", __func__,
+ data[11]);
+ search_sensitivity = data[11];
+ }
+#else
+ printk(KERN_DEBUG "called %s data[16] =%d,data[17] = %d\n", __func__,
+ data[16], data[17]);
+ search_sensitivity = ((0x00FF & data[16]) << 8) | data[17];
+#endif /* CONFIG_TARGET_LOCALE_NA */
+ return sprintf(buf, "%d\n", search_sensitivity);
+}
+#else
+static ssize_t touchkey_menu_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct touchkey_i2c *tkey_i2c = dev_get_drvdata(dev);
+#if defined(CONFIG_MACH_Q1_BD) \
+|| (defined(CONFIG_MACH_C1) && defined(CONFIG_TARGET_LOCALE_KOR))
+ u8 data[14] = { 0, };
+ int ret;
+
+ ret = i2c_touchkey_read(tkey_i2c->client, KEYCODE_REG, data, 14);
+
+ printk(KERN_DEBUG "called %s data[13] =%d\n", __func__, data[13]);
+ menu_sensitivity = data[13];
+#else
+ u8 data[10];
+ int ret;
+
+ printk(KERN_DEBUG "called %s\n", __func__);
+ ret = i2c_touchkey_read(tkey_i2c->client, KEYCODE_REG, data, 10);
+ menu_sensitivity = data[7];
+#endif
+ return sprintf(buf, "%d\n", menu_sensitivity);
+}
+
+static ssize_t touchkey_back_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct touchkey_i2c *tkey_i2c = dev_get_drvdata(dev);
+#if defined(CONFIG_MACH_Q1_BD) \
+|| (defined(CONFIG_MACH_C1) && defined(CONFIG_TARGET_LOCALE_KOR))
+ u8 data[14] = { 0, };
+ int ret;
+
+ ret = i2c_touchkey_read(tkey_i2c->client, KEYCODE_REG, data, 14);
+
+ printk(KERN_DEBUG "called %s data[11] =%d\n", __func__, data[11]);
+ back_sensitivity = data[11];
+#else
+ u8 data[10];
+ int ret;
+
+ printk(KERN_DEBUG "called %s\n", __func__);
+ ret = i2c_touchkey_read(tkey_i2c->client, KEYCODE_REG, data, 10);
+ back_sensitivity = data[9];
+#endif
+ return sprintf(buf, "%d\n", back_sensitivity);
+}
+#endif
+
+#if defined(TK_HAS_AUTOCAL)
+static ssize_t autocalibration_enable(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t size)
+{
+ struct touchkey_i2c *tkey_i2c = dev_get_drvdata(dev);
+ int data;
+
+ sscanf(buf, "%d\n", &data);
+
+ if (data == 1)
+ touchkey_autocalibration(tkey_i2c);
+
+ return size;
+}
+
+static ssize_t autocalibration_status(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ u8 data[6];
+ int ret;
+ struct touchkey_i2c *tkey_i2c = dev_get_drvdata(dev);
+
+ printk(KERN_DEBUG "[Touchkey] %s\n", __func__);
+
+ ret = i2c_touchkey_read(tkey_i2c->client, KEYCODE_REG, data, 6);
+ if ((data[5] & TK_BIT_AUTOCAL))
+ return sprintf(buf, "Enabled\n");
+ else
+ return sprintf(buf, "Disabled\n");
+
+}
+#endif /* CONFIG_TARGET_LOCALE_NA */
+
+static ssize_t touch_sensitivity_control(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t size)
+{
+ struct touchkey_i2c *tkey_i2c = dev_get_drvdata(dev);
+ unsigned char data = 0x40;
+ i2c_touchkey_write(tkey_i2c->client, &data, 1);
+ return size;
+}
+
+static ssize_t set_touchkey_firm_version_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ return sprintf(buf, "0x%x\n", TK_FIRMWARE_VER);
+}
+
+static ssize_t set_touchkey_update_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct touchkey_i2c *tkey_i2c = dev_get_drvdata(dev);
+ int count = 0;
+ int retry = 3;
+
+ tkey_i2c->update_status = TK_UPDATE_DOWN;
+
+ disable_irq(tkey_i2c->irq);
+
+#ifdef TEST_JIG_MODE
+ unsigned char get_touch = 0x40;
+#endif
+
+ while (retry--) {
+ if (ISSP_main(tkey_i2c) == 0) {
+ printk(KERN_ERR
+ "[TouchKey]Touchkey_update succeeded\n");
+ tkey_i2c->update_status = TK_UPDATE_PASS;
+ count = 1;
+ msleep(50);
+ break;
+ }
+ printk(KERN_ERR "touchkey_update failed... retry...\n");
+ }
+ if (retry <= 0) {
+ /* disable ldo11 */
+ tkey_i2c->pdata->power_on(0);
+ count = 0;
+ printk(KERN_ERR "[TouchKey]Touchkey_update fail\n");
+ tkey_i2c->update_status = TK_UPDATE_FAIL;
+ enable_irq(tkey_i2c->irq);
+ return count;
+ }
+
+#ifdef TEST_JIG_MODE
+ i2c_touchkey_write(tkey_i2c->client, &get_touch, 1);
+#endif
+
+ enable_irq(tkey_i2c->irq);
+
+ return count;
+
+}
+
+static ssize_t set_touchkey_firm_version_read_show(struct device *dev,
+ struct device_attribute
+ *attr, char *buf)
+{
+ struct touchkey_i2c *tkey_i2c = dev_get_drvdata(dev);
+ char data[3] = { 0, };
+ int count;
+
+ i2c_touchkey_read(tkey_i2c->client, KEYCODE_REG, data, 3);
+ count = sprintf(buf, "0x%x\n", data[1]);
+
+ printk(KERN_DEBUG "[TouchKey] touch_version_read 0x%x\n", data[1]);
+ printk(KERN_DEBUG "[TouchKey] module_version_read 0x%x\n", data[2]);
+ return count;
+}
+
+static ssize_t set_touchkey_firm_status_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct touchkey_i2c *tkey_i2c = dev_get_drvdata(dev);
+ int count = 0;
+
+ printk(KERN_DEBUG
+ "[TouchKey] touch_update_read: update_status %d\n",
+ tkey_i2c->update_status);
+
+ if (tkey_i2c->update_status == TK_UPDATE_PASS)
+ count = sprintf(buf, "PASS\n");
+ else if (tkey_i2c->update_status == TK_UPDATE_DOWN)
+ count = sprintf(buf, "Downloading\n");
+ else if (tkey_i2c->update_status == TK_UPDATE_FAIL)
+ count = sprintf(buf, "Fail\n");
+
+ return count;
+}
+
+static DEVICE_ATTR(recommended_version, S_IRUGO | S_IWUSR | S_IWGRP,
+ touch_version_read, touch_version_write);
+static DEVICE_ATTR(updated_version, S_IRUGO | S_IWUSR | S_IWGRP,
+ touch_update_read, touch_update_write);
+static DEVICE_ATTR(brightness, S_IRUGO | S_IWUSR | S_IWGRP, NULL,
+ touchkey_led_control);
+static DEVICE_ATTR(touchkey_menu, S_IRUGO | S_IWUSR | S_IWGRP,
+ touchkey_menu_show, NULL);
+static DEVICE_ATTR(touchkey_back, S_IRUGO | S_IWUSR | S_IWGRP,
+ touchkey_back_show, NULL);
+
+#if defined(CONFIG_TARGET_LOCALE_NA) || defined(CONFIG_TARGET_LOCALE_NAATT)
+static DEVICE_ATTR(touchkey_home, S_IRUGO, touchkey_home_show, NULL);
+static DEVICE_ATTR(touchkey_search, S_IRUGO, touchkey_search_show, NULL);
+#endif
+
+static DEVICE_ATTR(touch_sensitivity, S_IRUGO | S_IWUSR | S_IWGRP, NULL,
+ touch_sensitivity_control);
+static DEVICE_ATTR(touchkey_firm_update, S_IRUGO | S_IWUSR | S_IWGRP,
+ set_touchkey_update_show, NULL);
+static DEVICE_ATTR(touchkey_firm_update_status, S_IRUGO | S_IWUSR | S_IWGRP,
+ set_touchkey_firm_status_show, NULL);
+static DEVICE_ATTR(touchkey_firm_version_phone, S_IRUGO | S_IWUSR | S_IWGRP,
+ set_touchkey_firm_version_show, NULL);
+static DEVICE_ATTR(touchkey_firm_version_panel, S_IRUGO | S_IWUSR | S_IWGRP,
+ set_touchkey_firm_version_read_show, NULL);
+#ifdef LED_LDO_WITH_REGULATOR
+static DEVICE_ATTR(touchkey_brightness, S_IRUGO | S_IWUSR | S_IWGRP, NULL,
+ brightness_control);
+#endif
+
+#if defined(CONFIG_TARGET_LOCALE_NAATT)
+static DEVICE_ATTR(touchkey_autocal_start, S_IRUGO | S_IWUSR | S_IWGRP, NULL,
+ set_touchkey_autocal_testmode);
+#endif
+
+#if defined(TK_HAS_AUTOCAL)
+static DEVICE_ATTR(touchkey_raw_data0, S_IRUGO, touchkey_raw_data0_show, NULL);
+static DEVICE_ATTR(touchkey_raw_data1, S_IRUGO, touchkey_raw_data1_show, NULL);
+static DEVICE_ATTR(touchkey_raw_data2, S_IRUGO, touchkey_raw_data2_show, NULL);
+static DEVICE_ATTR(touchkey_raw_data3, S_IRUGO, touchkey_raw_data3_show, NULL);
+static DEVICE_ATTR(touchkey_idac0, S_IRUGO, touchkey_idac0_show, NULL);
+static DEVICE_ATTR(touchkey_idac1, S_IRUGO, touchkey_idac1_show, NULL);
+static DEVICE_ATTR(touchkey_idac2, S_IRUGO, touchkey_idac2_show, NULL);
+static DEVICE_ATTR(touchkey_idac3, S_IRUGO, touchkey_idac3_show, NULL);
+static DEVICE_ATTR(touchkey_threshold, S_IRUGO, touchkey_threshold_show, NULL);
+static DEVICE_ATTR(autocal_enable, S_IRUGO | S_IWUSR | S_IWGRP, NULL,
+ autocalibration_enable);
+static DEVICE_ATTR(autocal_stat, S_IRUGO | S_IWUSR | S_IWGRP,
+ autocalibration_status, NULL);
+#endif
+
+static struct attribute *touchkey_attributes[] = {
+ &dev_attr_recommended_version.attr,
+ &dev_attr_updated_version.attr,
+ &dev_attr_brightness.attr,
+ &dev_attr_touchkey_menu.attr,
+ &dev_attr_touchkey_back.attr,
+#if defined(CONFIG_TARGET_LOCALE_NA) || defined(CONFIG_TARGET_LOCALE_NAATT)
+ &dev_attr_touchkey_home.attr,
+ &dev_attr_touchkey_search.attr,
+#endif
+ &dev_attr_touch_sensitivity.attr,
+ &dev_attr_touchkey_firm_update.attr,
+ &dev_attr_touchkey_firm_update_status.attr,
+ &dev_attr_touchkey_firm_version_phone.attr,
+ &dev_attr_touchkey_firm_version_panel.attr,
+#ifdef LED_LDO_WITH_REGULATOR
+ &dev_attr_touchkey_brightness.attr,
+#endif
+#if defined(CONFIG_TARGET_LOCALE_NAATT)
+ &dev_attr_touchkey_autocal_start.attr,
+#endif
+#if defined(TK_HAS_AUTOCAL)
+ &dev_attr_touchkey_raw_data0.attr,
+ &dev_attr_touchkey_raw_data1.attr,
+ &dev_attr_touchkey_raw_data2.attr,
+ &dev_attr_touchkey_raw_data3.attr,
+ &dev_attr_touchkey_idac0.attr,
+ &dev_attr_touchkey_idac1.attr,
+ &dev_attr_touchkey_idac2.attr,
+ &dev_attr_touchkey_idac3.attr,
+ &dev_attr_touchkey_threshold.attr,
+ &dev_attr_autocal_enable.attr,
+ &dev_attr_autocal_stat.attr,
+#endif
+ NULL,
+};
+
+static struct attribute_group touchkey_attr_group = {
+ .attrs = touchkey_attributes,
+};
+
+static int i2c_touchkey_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ struct touchkey_platform_data *pdata = client->dev.platform_data;
+ struct touchkey_i2c *tkey_i2c;
+
+ struct input_dev *input_dev;
+ int err = 0;
+ unsigned char data;
+ int i;
+ int ret;
+
+ printk(KERN_DEBUG "[TouchKey] i2c_touchkey_probe\n");
+
+ if (pdata == NULL) {
+ printk(KERN_ERR "%s: no pdata\n", __func__);
+ return -ENODEV;
+ }
+
+ /*Check I2C functionality */
+ ret = i2c_check_functionality(client->adapter, I2C_FUNC_I2C);
+ if (ret == 0) {
+ printk(KERN_ERR "[Touchkey] No I2C functionality found\n");
+ ret = -ENODEV;
+ return ret;
+ }
+
+ /*Obtain kernel memory space for touchkey i2c */
+ tkey_i2c = kzalloc(sizeof(struct touchkey_i2c), GFP_KERNEL);
+ if (NULL == tkey_i2c) {
+ printk(KERN_ERR "[Touchkey] failed to allocate tkey_i2c.\n");
+ return -ENOMEM;
+ }
+
+ input_dev = input_allocate_device();
+
+ if (!input_dev) {
+ printk(KERN_ERR"[Touchkey] failed to allocate input device\n");
+ kfree(tkey_i2c);
+ return -ENOMEM;
+ }
+
+ input_dev->name = "sec_touchkey";
+ input_dev->phys = "sec_touchkey/input0";
+ input_dev->id.bustype = BUS_HOST;
+ input_dev->dev.parent = &client->dev;
+
+ /*tkey_i2c*/
+ tkey_i2c->pdata = pdata;
+ tkey_i2c->input_dev = input_dev;
+ tkey_i2c->client = client;
+ tkey_i2c->irq = client->irq;
+ tkey_i2c->name = "sec_touchkey";
+
+ set_bit(EV_SYN, input_dev->evbit);
+ set_bit(EV_LED, input_dev->evbit);
+ set_bit(LED_MISC, input_dev->ledbit);
+ set_bit(EV_KEY, input_dev->evbit);
+
+ for (i = 1; i < touchkey_count; i++)
+ set_bit(touchkey_keycode[i], input_dev->keybit);
+
+ input_set_drvdata(input_dev, tkey_i2c);
+
+ ret = input_register_device(input_dev);
+ if (ret) {
+ printk(KERN_ERR"[Touchkey] failed to register input device\n");
+ input_free_device(input_dev);
+ kfree(tkey_i2c);
+ return err;
+ }
+
+ INIT_WORK(&tkey_i2c->update_work, touchkey_update_func);
+
+ tkey_i2c->pdata->power_on(1);
+ msleep(50);
+
+ touchkey_enable = 1;
+ data = 1;
+
+ /*sysfs*/
+ tkey_i2c->dev = device_create(sec_class, NULL, 0, NULL, "sec_touchkey");
+
+ if (IS_ERR(tkey_i2c->dev)) {
+ printk(KERN_ERR "Failed to create device(tkey_i2c->dev)!\n");
+ input_unregister_device(input_dev);
+ } else {
+ dev_set_drvdata(tkey_i2c->dev, tkey_i2c);
+ ret = sysfs_create_group(&tkey_i2c->dev->kobj,
+ &touchkey_attr_group);
+ if (ret) {
+ printk(KERN_ERR
+ "[TouchKey]: failed to create sysfs group\n");
+ }
+ }
+
+ ret =
+ request_threaded_irq(tkey_i2c->irq, NULL, touchkey_interrupt,
+ IRQF_DISABLED | IRQF_TRIGGER_FALLING |
+ IRQF_ONESHOT, tkey_i2c->name, tkey_i2c);
+ if (ret < 0) {
+ printk(KERN_ERR
+ "[Touchkey]: failed to request irq(%d) - %d\n",
+ tkey_i2c->irq, ret);
+ input_unregister_device(input_dev);
+ touchkey_probe = false;
+ return -EBUSY;
+ }
+
+#ifdef CONFIG_HAS_EARLYSUSPEND
+ tkey_i2c->early_suspend.suspend =
+ (void *)sec_touchkey_early_suspend;
+ tkey_i2c->early_suspend.resume =
+ (void *)sec_touchkey_late_resume;
+ register_early_suspend(&tkey_i2c->early_suspend);
+#endif
+
+ tkey_i2c->pdata->led_power_on(1);
+
+#if defined(TK_HAS_FIRMWARE_UPDATE)
+ ret = touchkey_firmware_update(tkey_i2c);
+ if (ret < 0) {
+ printk(KERN_ERR
+ "[Touchkey]: failed firmware updating process (%d)\n",
+ ret);
+ input_unregister_device(input_dev);
+ touchkey_probe = false;
+ return -EBUSY;
+ }
+#endif
+
+#if defined(TK_HAS_AUTOCAL)
+ touchkey_autocalibration(tkey_i2c);
+#endif
+ set_touchkey_debug('K');
+ return 0;
+}
+
+struct i2c_driver touchkey_i2c_driver = {
+ .driver = {
+ .name = "sec_touchkey_driver",
+ },
+ .id_table = sec_touchkey_id,
+ .probe = i2c_touchkey_probe,
+};
+
+static int __init touchkey_init(void)
+{
+ int ret = 0;
+
+#if defined(CONFIG_MACH_M0) || defined(CONFIG_MACH_C1VZW)
+ if (system_rev < TOUCHKEY_FW_UPDATEABLE_HW_REV) {
+ printk(KERN_DEBUG "[Touchkey] Doesn't support this board rev %d\n",
+ system_rev);
+ return 0;
+ }
+#elif defined(CONFIG_MACH_C1)
+ if (system_rev < TOUCHKEY_FW_UPDATEABLE_HW_REV) {
+ printk(KERN_DEBUG "[Touchkey] Doesn't support this board rev %d\n",
+ system_rev);
+ return 0;
+ }
+#endif
+
+#ifdef TEST_JIG_MODE
+ unsigned char get_touch = 0x40;
+#endif
+
+ ret = i2c_add_driver(&touchkey_i2c_driver);
+
+ if (ret) {
+ printk(KERN_ERR
+ "[TouchKey] registration failed, module not inserted.ret= %d\n",
+ ret);
+ }
+#ifdef TEST_JIG_MODE
+ i2c_touchkey_write(tkey_i2c->client, &get_touch, 1);
+#endif
+ return ret;
+}
+
+static void __exit touchkey_exit(void)
+{
+ printk(KERN_DEBUG "[TouchKey] %s\n", __func__);
+ i2c_del_driver(&touchkey_i2c_driver);
+}
+
+late_initcall(touchkey_init);
+module_exit(touchkey_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("@@@");
+MODULE_DESCRIPTION("touch keypad");