(CR):[kane]:kernel: add sar sensor sx9325 drivers
authorhq_guohongtao5_tmp <guohongtao5@huaqin.com>
Wed, 29 Aug 2018 08:11:20 +0000 (16:11 +0800)
committerxiest1 <xiest1@lenovo.com>
Tue, 5 Nov 2019 09:29:40 +0000 (17:29 +0800)
add sar sensor sx9325 drivers

Change-Id: I701d32e90ad56d0444df5b8029de6225bf3acf10
Signed-off-by: hq_guohongtao5_tmp <guohongtao5@huaqin.com>
drivers/input/misc/Makefile
drivers/input/misc/sx9325_sar.c [new file with mode: 0755]
drivers/input/misc/sx9325_sar.h [new file with mode: 0755]
drivers/input/misc/sx932x.c [deleted file]
drivers/input/misc/sx932x.h [deleted file]
include/linux/sensors.h

index f2cd79560060ffbbf04a9f09fce69e89b60f300f..b9e8ce9cf087dd5676ddc6db7429c2f1f8d024a7 100755 (executable)
@@ -84,4 +84,4 @@ obj-$(CONFIG_INPUT_XEN_KBDDEV_FRONTEND)       += xen-kbdfront.o
 obj-$(CONFIG_INPUT_YEALINK)            += yealink.o
 obj-$(CONFIG_INPUT_IDEAPAD_SLIDEBAR)   += ideapad_slidebar.o
 obj-$(CONFIG_INPUT_S2MU106_HAPTIC)     += s2mu106_haptic.o
-obj-$(CONFIG_SARSENSOR_SX9325) += sx932x.o
\ No newline at end of file
+obj-$(CONFIG_SARSENSOR_SX9325) += sx9325_sar.o
diff --git a/drivers/input/misc/sx9325_sar.c b/drivers/input/misc/sx9325_sar.c
new file mode 100755 (executable)
index 0000000..7eb01fb
--- /dev/null
@@ -0,0 +1,1717 @@
+/*
+ * file sx9325_sar.c
+ * brief SX9325 Driver for two channel SAP using
+ *
+ * Driver for the SX9325
+ * Copyright (c) 2015-2016 Semtech Corp
+ *
+ * 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.
+ */
+#define DEBUG
+#define DRIVER_NAME "sx9325"
+#define USE_SENSORS_CLASS
+#define USE_KERNEL_SUSPEND
+
+#define MAX_WRITE_ARRAY_SIZE 32
+
+#include <linux/irq.h>
+#include <linux/slab.h>
+#include <linux/workqueue.h>
+
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/i2c.h>
+#include <linux/delay.h>
+#include <linux/input.h>
+#include <linux/of.h>
+#include <linux/of_gpio.h>
+#include <linux/gpio.h>
+#include <linux/device.h>
+#include <linux/sensors.h>
+#include <linux/interrupt.h>
+#include <linux/regulator/consumer.h>
+#include <linux/notifier.h>
+#include <linux/usb.h>
+#include <linux/power_supply.h>
+
+#if defined(CONFIG_FB)
+#include <linux/fb.h>
+#endif
+
+/* main struct, interrupt,init,pointers */
+#include "sx9325_sar.h"
+
+
+#define IDLE 0
+#define ACTIVE 1
+#define S_PROX   1
+#define S_BODY   2
+
+#define SX9325_DEBUG 1
+#define LOG_TAG "SX9325 "
+
+#if SX9325_DEBUG
+#define LOG_INFO(fmt, args...)    pr_info(LOG_TAG fmt, ##args)
+#else
+#define LOG_INFO(fmt, args...)
+#endif
+
+#define LOG_DBG(fmt, args...)  pr_debug(LOG_TAG fmt, ##args)
+#define LOG_ERR(fmt, args...)  pr_err(LOG_TAG fmt, ##args)
+
+static int sx9325_debug_enable = 1;
+
+static int last_val;
+static int mEnabled;
+static int programming_done;
+psx93XX_t sx9325_sar_ptr;
+
+/**
+ * struct sx9325
+ * Specialized struct containing input event data, platform data, and
+ * last cap state read if needed.
+ */
+typedef struct sx9325 {
+       pbuttonInformation_t pbuttonInformation;
+       psx9325_platform_data_t hw; /* specific platform data settings */
+} sx9325_t, *psx9325_t;
+
+static void ForcetoTouched(psx93XX_t this)
+{
+       psx9325_t pDevice = NULL;
+       struct input_dev *input_top = NULL;
+       struct input_dev *input_bottom = NULL;
+       struct _buttonInfo *pCurrentButton  = NULL;
+
+       pDevice = this->pDevice;
+       if (this && pDevice) {
+               LOG_INFO("ForcetoTouched()\n");
+
+               pCurrentButton = pDevice->pbuttonInformation->buttons;
+               input_top = pDevice->pbuttonInformation->input_top;
+               input_bottom = pDevice->pbuttonInformation->input_bottom;
+               pCurrentButton->state = ACTIVE;
+               last_val = 1;
+               if (mEnabled) {
+                       input_report_abs(input_top, ABS_DISTANCE, 1);
+                       input_sync(input_top);
+                       input_report_abs(input_bottom, ABS_DISTANCE, 1);
+                       input_sync(input_bottom);
+               }
+               LOG_INFO("Leaving ForcetoTouched()\n");
+       }
+}
+
+/**
+ * fn static int write_register(psx93XX_t this, u8 address, u8 value)
+ * brief Sends a write register to the device
+ * param this Pointer to main parent struct
+ * param address 8-bit register address
+ * param value   8-bit register value to write to address
+ * return Value from i2c_master_send
+ */
+static int write_register(psx93XX_t this, u8 address, u8 value)
+{
+       struct i2c_client *i2c = 0;
+       char buffer[2];
+       int returnValue = 0;
+
+       buffer[0] = address;
+       buffer[1] = value;
+       returnValue = -ENOMEM;
+       if (this && this->bus) {
+               i2c = this->bus;
+
+               returnValue = i2c_master_send(i2c, buffer, 2);
+               if (sx9325_debug_enable)
+                       LOG_DBG("write_register Addr: \
+                               0x%x Val: 0x%x Return: %d\n",
+                               address, value, returnValue);
+       }
+       if (returnValue < 0) {
+               ForcetoTouched(this);
+               LOG_INFO("Write_register-ForcetoTouched()\n");
+       }
+       return returnValue;
+}
+
+/**
+ * fn static int read_register(psx93XX_t this, u8 address, u8 *value)
+ * brief Reads a register's value from the device
+ * param this Pointer to main parent struct
+ * param address 8-Bit address to read from
+ * param value Pointer to 8-bit value to save register value to
+ * return Value from i2c_smbus_read_byte_data if < 0. else 0
+ */
+static int read_register(psx93XX_t this, u8 address, u8 *value)
+{
+       struct i2c_client *i2c = 0;
+       s32 returnValue = 0;
+
+       if (this && value && this->bus) {
+               i2c = this->bus;
+               returnValue = i2c_smbus_read_byte_data(i2c, address);
+               if (sx9325_debug_enable)
+                       LOG_DBG("read_register Addr: 0x%x Return: 0x%x\n",
+                               address, returnValue);
+               if (returnValue >= 0) {
+                       *value = returnValue;
+                       return 0;
+               } else {
+                       return returnValue;
+               }
+       }
+       ForcetoTouched(this);
+       LOG_INFO("read_register-ForcetoTouched()\n");
+       return -ENOMEM;
+}
+
+/**
+ * detect if sx9325 exist or not
+ * return 1 if chip exist else return 0
+ */
+static int sx9325_detect(struct i2c_client *client)
+{
+       s32 returnValue = 0, i;
+       u8 address = SX932x_WHOAMI_REG;
+       u8 value_9325 = SX932x_WHOAMI_VALUE;
+
+       if (client) {
+               for (i = 0; i < 3; i++) {
+                       returnValue = i2c_smbus_read_byte_data(client, address);
+                       LOG_INFO("sx9325 read_register for %d time Addr:\
+                                       0x%x Return: 0x%x\n",
+                                       i, address, returnValue);
+                       if (value_9325 == returnValue){
+                               LOG_INFO("sx9325 detect success !\n");
+                               return 1;
+                       }
+               }
+       }
+       LOG_ERR("sx9325 detect failed !!!\n");
+       return 0;
+}
+
+/**
+ * brief Perform a manual offset calibration
+ * param this Pointer to main parent struct
+ * return Value return value from the write register
+ */
+static int manual_offset_calibration(psx93XX_t this)
+{
+       s32 returnValue = 0;
+
+       returnValue = write_register(this,SX932x_STAT2_REG,0x0F);
+       return returnValue;
+}
+
+/**
+ * brief sysfs show function for manual calibration which currently just
+ * returns register value.
+ */
+
+static ssize_t manual_offset_calibration_show(struct device *dev,
+               struct device_attribute *attr, char *buf)
+{
+       u8 reg_value = 0;
+       psx93XX_t this = dev_get_drvdata(dev);
+
+       LOG_INFO("Reading IRQSTAT_REG\n");
+       read_register(this, SX932x_IRQSTAT_REG, &reg_value);
+       return scnprintf(buf, PAGE_SIZE, "%d\n", reg_value);
+}
+
+/* brief sysfs store function for manual calibration */
+static ssize_t manual_offset_calibration_store(struct device *dev,
+               struct device_attribute *attr,
+               const char *buf, size_t count)
+{
+       psx93XX_t this = dev_get_drvdata(dev);
+       unsigned long val;
+
+       if (kstrtoul(buf, 0, &val))
+               return -EINVAL;
+       if (val) {
+               LOG_INFO("Performing manual_offset_calibration()\n");
+               manual_offset_calibration(this);
+       }
+       return count;
+}
+
+static DEVICE_ATTR(calibrate, 0644, manual_offset_calibration_show,
+               manual_offset_calibration_store);
+static struct attribute *sx9325_attributes[] = {
+       &dev_attr_calibrate.attr,
+       NULL,
+};
+static struct attribute_group sx9325_attr_group = {
+       .attrs = sx9325_attributes,
+};
+
+/**
+ * fn static int read_regStat(psx93XX_t this)
+ * brief Shortcut to read what caused interrupt.
+ * details This is to keep the drivers a unified
+ * function that will read whatever register(s)
+ * provide information on why the interrupt was caused.
+ * param this Pointer to main parent struct
+ * return If successful, Value of bit(s) that cause interrupt, else 0
+ */
+static int read_regStat(psx93XX_t this)
+{
+       u8 data = 0;
+
+       if (this) {
+               if (read_register(this, SX932x_IRQSTAT_REG, &data) == 0)
+                       return (data & 0x00FF);
+       }
+       return 0;
+}
+
+static void read_rawData(psx93XX_t this)
+{
+       u8 msb = 0, lsb = 0;
+       unsigned int ii;
+
+       if (this) {
+               for (ii = 0; ii < USE_CHANNEL_NUM; ii++) {
+                       /* here to check the CSx */
+                       write_register(this, SX932x_CPSRD, ii);
+                       msleep(100);
+                       read_register(this, SX932x_USEMSB, &msb);
+                       read_register(this, SX932x_USELSB, &lsb);
+                       LOG_INFO("sx9325 cs%d USEFUL msb = 0x%x, lsb = 0x%x\n",
+                                       ii, msb, lsb);
+                       read_register(this, SX932x_AVGMSB, &msb);
+                       read_register(this, SX932x_AVGLSB, &lsb);
+                       LOG_INFO("sx9325 cs%d AVERAGE msb = 0x%x, lsb = 0x%x\n",
+                                       ii, msb, lsb);
+                       read_register(this, SX932x_DIFFMSB, &msb);
+                       read_register(this, SX932x_DIFFLSB, &lsb);
+                       LOG_INFO("sx9325 cs%d DIFF msb = 0x%x, lsb = 0x%x\n",
+                                       ii, msb, lsb);
+                       read_register(this, SX932x_OFFSETMSB, &msb);
+                       read_register(this, SX932x_OFFSETLSB, &lsb);
+                       LOG_INFO("sx9325 cs%d OFFSET msb = 0x%x, lsb = 0x%x\n",
+                                       ii, msb, lsb);
+               }
+       }
+}
+
+/**
+ * brief  Initialize I2C config from platform data
+ * param this Pointer to main parent struct
+ *
+ */
+static void hw_init(psx93XX_t this)
+{
+       psx9325_t pDevice = 0;
+       psx9325_platform_data_t pdata = 0;
+       int i = 0;
+       /* configure device */
+       LOG_INFO("Going to Setup I2C Registers\n");
+       pDevice = this->pDevice;
+       pdata = pDevice->hw;
+       if (this && pDevice && pdata) {
+               while (i < pdata->i2c_reg_num) {
+                       /* Write all registers/values contained in i2c_reg */
+                       if (sx9325_debug_enable)
+                               LOG_DBG("Going to Write Reg: \
+                                       0x%x Value: 0x%x\n",
+                                       pdata->pi2c_reg[i].reg,
+                                       pdata->pi2c_reg[i].val);
+                       write_register(this, pdata->pi2c_reg[i].reg,
+                                       pdata->pi2c_reg[i].val);
+                       i++;
+               }
+
+               write_register(this, SX932x_CTRL1_REG,
+                               this->board->cust_prox_ctrl0);
+               write_register(this, SX932x_CPSRD,
+                               this->board->cust_raw_data_channel);
+       } else {
+               LOG_ERR("ERROR! platform data 0x%p\n", pDevice->hw);
+               /* Force to touched if error */
+               ForcetoTouched(this);
+               LOG_INFO("Hardware_init-ForcetoTouched()\n");
+       }
+}
+
+/**
+ * fn static int initialize(psx93XX_t this)
+ * brief Performs all initialization needed to configure the device
+ * param this Pointer to main parent struct
+ * return Last used command's return value (negative if error)
+ */
+static int initialize(psx93XX_t this)
+{
+       int ret;
+
+       if (this) {
+               /* prepare reset by disabling any irq handling */
+               this->irq_disabled = 1;
+               disable_irq(this->irq);
+               /* perform a reset */
+               ret = write_register(this, SX932x_SOFTRESET_REG,
+                               SX932x_SOFTRESET);
+               if (ret < 0)
+                       goto error_exit;
+               /* wait until the reset has finished by monitoring NIRQ */
+               LOG_INFO("Software Reset. Waiting device back to continue.\n");
+               /* just sleep for awhile instead of using a loop
+                * with reading irq status */
+               msleep(300);
+               /*
+                * while(this->get_nirq_low && this->get_nirq_low())
+                * { read_regStat(this); }
+                */
+               LOG_INFO("Device back from the reset, continuing. NIRQ = %d\n",
+                               this->get_nirq_low(this->board->irq_gpio));
+               hw_init(this);
+               msleep(100); /* make sure everything is running */
+               ret = manual_offset_calibration(this);
+               if (ret < 0)
+                       goto error_exit;
+               /* re-enable interrupt handling */
+               enable_irq(this->irq);
+               this->irq_disabled = 0;
+
+               /* make sure no interrupts are pending
+                * since enabling irq will only
+                * work on next falling edge */
+               read_regStat(this);
+               LOG_INFO("Exiting initialize(). NIRQ = %d\n",
+                               this->get_nirq_low(this->board->irq_gpio));
+               programming_done = ACTIVE;
+               return 0;
+       }
+       return -ENOMEM;
+
+error_exit:
+       programming_done = IDLE;
+       return ret;
+}
+
+/**
+ * brief Handle what to do when a touch occurs
+ * param this Pointer to main parent struct
+ */
+static void touchProcess(psx93XX_t this)
+{
+       int counter = 0;
+       u8 i = 0;
+       u8 Lsb,Msb;
+       int numberOfButtons = 0;
+       psx9325_t pDevice = NULL;
+       struct _buttonInfo *buttons = NULL;
+       struct input_dev *input_top = NULL;
+       struct input_dev *input_bottom = NULL;
+       struct _buttonInfo *pCurrentButton  = NULL;
+       struct sx9325_platform_data *board;
+
+       pDevice = this->pDevice;
+       board = this->board;
+       if (this && pDevice) {
+               if (sx9325_debug_enable)
+                       LOG_DBG("Inside touchProcess()\n");
+
+               read_register(this, SX932x_STAT0_REG, &Lsb);
+               read_register(this, SX932x_STAT1_REG, &Msb);
+               Lsb = (u8)(Lsb&0x0F);
+               Msb = (u8)(Msb&0x0F);
+        i = (u8)((Msb<<4)|Lsb);
+
+               buttons = pDevice->pbuttonInformation->buttons;
+               input_top = pDevice->pbuttonInformation->input_top;
+               input_bottom = pDevice->pbuttonInformation->input_bottom;
+               numberOfButtons = pDevice->pbuttonInformation->buttonSize;
+
+               if (unlikely((buttons == NULL) || (input_top == NULL) ||
+                                                (input_bottom == NULL))) {
+                       LOG_ERR("ERROR!! buttons or input NULL!!!\n");
+                       return;
+               }
+
+               for (counter = 0; counter < numberOfButtons; counter++) {
+                       pCurrentButton = &buttons[counter];
+                       if (pCurrentButton == NULL) {
+                               LOG_ERR("ERR!current button index: %d NULL!\n",
+                                               counter);
+                               return; /* ERRORR!!!! */
+                       }
+                       switch (pCurrentButton->state) {
+                       case IDLE: /* Button is being in far state! */
+                               if ((i & pCurrentButton->mask) ==
+                                                        pCurrentButton->mask) {
+                                       LOG_INFO("CS %d State=BODY.\n",
+                                                       counter);
+                                       if (board->cap_channel_top == counter) {
+                                               input_report_abs(input_top,
+                                                       ABS_DISTANCE, 2);
+                                               input_sync(input_top);
+                                       } else if (board->cap_channel_bottom ==
+                                                                counter) {
+                                               input_report_abs(input_bottom,
+                                                        ABS_DISTANCE, 2);
+                                               input_sync(input_bottom);
+                                       }
+                                       pCurrentButton->state = S_BODY;
+                                       last_val = 2;
+                               } else if ((i & pCurrentButton->mask) ==
+                                          (pCurrentButton->mask & 0x0f)) {
+                                       LOG_INFO("CS %d State=PROX.\n",
+                                                       counter);
+                                       if (board->cap_channel_top == counter) {
+                                               input_report_abs(input_top,
+                                                       ABS_DISTANCE, 1);
+                                               input_sync(input_top);
+                                       } else if (board->cap_channel_bottom ==
+                                                                counter) {
+                                               input_report_abs(input_bottom,
+                                                        ABS_DISTANCE, 1);
+                                               input_sync(input_bottom);
+                                       }
+                                       pCurrentButton->state = S_PROX;
+                                       last_val = 0;
+                               } else {
+                                       if (sx9325_debug_enable)
+                                               LOG_DBG("CS %d still in"
+                                                         "IDLE State.\n",
+                                                         counter);
+                               }
+                               break;
+                       case S_PROX: /* Button is being in proximity! */
+                               if ((i & pCurrentButton->mask) ==
+                                                        pCurrentButton->mask) {
+                                       LOG_INFO("CS %d State=BODY.\n",
+                                                       counter);
+                                       if (board->cap_channel_top == counter) {
+                                               input_report_abs(input_top,
+                                                        ABS_DISTANCE, 2);
+                                               input_sync(input_top);
+                                       } else if (board->cap_channel_bottom ==
+                                                                counter) {
+                                               input_report_abs(input_bottom,
+                                                       ABS_DISTANCE, 2);
+                                               input_sync(input_bottom);
+                                       }
+                                       pCurrentButton->state = S_BODY;
+                                       last_val = 2;
+                               } else if ((i & pCurrentButton->mask) ==
+                                          (pCurrentButton->mask & 0x0f)) {
+                                       if (sx9325_debug_enable)
+                                               LOG_INFO("CS %d still in PROX State.\n",
+                                                       counter);
+                               } else{
+                                       if (sx9325_debug_enable)
+                                               LOG_DBG("CS %d State=IDLE.\n",
+                                                       counter);
+                                       if (board->cap_channel_top == counter) {
+                                               input_report_abs(input_top,
+                                                       ABS_DISTANCE, 0);
+                                               input_sync(input_top);
+                                       } else if (board->cap_channel_bottom ==
+                                                                counter) {
+                                               input_report_abs(input_bottom,
+                                                        ABS_DISTANCE, 0);
+                                               input_sync(input_bottom);
+                                       }
+                                       pCurrentButton->state = IDLE;
+                                       last_val = 0;
+                               }
+                               break;
+                       case S_BODY: /* Button is being in 0mm! */
+                               if ((i & pCurrentButton->mask) ==
+                                                        pCurrentButton->mask) {
+                                       if (sx9325_debug_enable)
+                                               LOG_INFO("CS %d still in BODY State.\n",
+                                                       counter);
+                               } else if ((i & pCurrentButton->mask) ==
+                                          (pCurrentButton->mask & 0x0f)) {
+                                       LOG_INFO("CS %d State=PROX.\n",
+                                                       counter);
+                                       if (board->cap_channel_top == counter) {
+                                               input_report_abs(input_top,
+                                                       ABS_DISTANCE, 1);
+                                               input_sync(input_top);
+                                       } else if (board->cap_channel_bottom
+                                                                == counter) {
+                                               input_report_abs(input_bottom,
+                                                        ABS_DISTANCE, 1);
+                                               input_sync(input_bottom);
+                                       }
+                                       pCurrentButton->state = S_PROX;
+                                       last_val = 1;
+                               } else{
+                                       if (sx9325_debug_enable)
+                                               LOG_DBG("CS %d State=IDLE.\n",
+                                                       counter);
+                                       if (board->cap_channel_top == counter) {
+                                               input_report_abs(input_top,
+                                                       ABS_DISTANCE, 0);
+                                               input_sync(input_top);
+                                       } else if (board->cap_channel_bottom
+                                                                == counter) {
+                                               input_report_abs(input_bottom,
+                                                       ABS_DISTANCE, 0);
+                                               input_sync(input_bottom);
+                                       }
+                                       pCurrentButton->state = IDLE;
+                                       last_val = 0;
+                               }
+                               break;
+                       /* Shouldn't be here, device only
+                        * allowed ACTIVE or IDLE */
+                       default:
+                               break;
+                       };
+               }
+               if (sx9325_debug_enable)
+                       LOG_DBG("Leaving touchProcess()\n");
+       }
+}
+
+static int sx9325_get_nirq_state(unsigned irq_gpio)
+{
+       if (irq_gpio)
+               return !gpio_get_value(irq_gpio);
+
+       LOG_ERR("sx9325 irq_gpio is not set.");
+       return -EINVAL;
+}
+
+static struct _totalButtonInformation smtcButtonInformation = {
+       .buttons = psmtcButtons,
+       .buttonSize = ARRAY_SIZE(psmtcButtons),
+};
+
+/**
+ *fn static void sx9325_reg_setup_init(struct i2c_client *client)
+ *brief read reg val form dts
+ *      reg_array_len for regs needed change num
+ *      data_array_val's format <reg val ...>
+ */
+static void sx9325_reg_setup_init(struct i2c_client *client)
+{
+       u32 data_array_len = 0;
+       u32 *data_array;
+       int ret, i, j;
+       struct device_node *np = client->dev.of_node;
+
+       ret = of_property_read_u32(np, "reg_array_len", &data_array_len);
+       if (ret < 0) {
+               LOG_ERR("data_array_len read error");
+               return;
+       }
+       data_array = kmalloc(data_array_len * 2 * sizeof(u32), GFP_KERNEL);
+       ret = of_property_read_u32_array(np, "reg_array_val",
+                       data_array,
+                       data_array_len*2);
+       if (ret < 0) {
+               LOG_ERR("data_array_val read error");
+               return;
+       }
+       for (i = 0; i < ARRAY_SIZE(sx9325_i2c_reg_setup); i++) {
+               for (j = 0; j < data_array_len*2; j += 2) {
+                       if (data_array[j] == sx9325_i2c_reg_setup[i].reg) {
+                               sx9325_i2c_reg_setup[i].val = data_array[j+1];
+                               LOG_INFO("read dtsi 0x%02x:0x%02x set reg\n",
+                                       data_array[j], data_array[j+1]);
+                       }
+               }
+       }
+       kfree(data_array);
+       /*for test*/
+       /*for (i = 0; i < ARRAY_SIZE(sx9325_i2c_reg_setup); i++) {
+         dev_err(&client->dev, "%x:%x",
+         sx9325_i2c_reg_setup[i].reg,
+         sx9325_i2c_reg_setup[i].val);
+         }*/
+}
+
+static void sx9325_platform_data_of_init(struct i2c_client *client,
+               psx9325_platform_data_t pplatData)
+{
+       struct device_node *np = client->dev.of_node;
+       u32 scan_period, sensor_en, raw_data_channel;
+       u32 cap_channel_top, cap_channel_bottom;
+       int ret;
+
+       client->irq = of_get_gpio(np, 0);
+       pplatData->irq_gpio = client->irq;
+
+       ret = of_property_read_u32(np, "cap,use_channel", &sensor_en);
+       if (ret)
+               sensor_en = DUMMY_USE_CHANNEL;
+
+       ret = of_property_read_u32(np, "cap,use_channel_top", &cap_channel_top);
+       if (ret)
+               sensor_en = DUMMY_USE_CHANNEL;
+
+       ret = of_property_read_u32(np, "cap,use_channel_bottom",
+                                       &cap_channel_bottom);
+       if (ret)
+               sensor_en = DUMMY_USE_CHANNEL;
+
+       ret = of_property_read_u32(np, "cap,scan_period", &scan_period);
+       if (ret)
+               scan_period = DUMMY_SCAN_PERIOD;
+
+       ret = of_property_read_u32(np, "cap,raw_data_channel",
+                                       &raw_data_channel);
+       if (ret)
+               raw_data_channel = DUMMY_RAW_DATA_CHANNEL;
+
+       pplatData->cust_prox_ctrl0 = (scan_period << 4) | sensor_en;
+       pplatData->cust_raw_data_channel = raw_data_channel;
+       pplatData->cap_channel_top = (int)cap_channel_top;
+       pplatData->cap_channel_bottom = (int)cap_channel_bottom;
+
+       pplatData->get_is_nirq_low = sx9325_get_nirq_state;
+       pplatData->init_platform_hw = NULL;
+       /*  pointer to an exit function. Here in case needed in the future */
+       /*
+        *.exit_platform_hw = sx9325_exit_ts,
+        */
+       pplatData->exit_platform_hw = NULL;
+       sx9325_reg_setup_init(client);
+       pplatData->pi2c_reg = sx9325_i2c_reg_setup;
+       pplatData->i2c_reg_num = ARRAY_SIZE(sx9325_i2c_reg_setup);
+
+       pplatData->pbuttonInformation = &smtcButtonInformation;
+}
+
+static ssize_t reset_show(struct class *class,
+               struct class_attribute *attr,
+               char *buf)
+{
+       return snprintf(buf, 8, "%d\n", programming_done);
+}
+
+static ssize_t reset_store(struct class *class,
+               struct class_attribute *attr,
+               const char *buf, size_t count)
+{
+       psx93XX_t this = sx9325_sar_ptr;
+       psx9325_t pDevice = NULL;
+       struct input_dev *input_top = NULL;
+       struct input_dev *input_bottom = NULL;
+
+       pDevice = this->pDevice;
+       input_top = pDevice->pbuttonInformation->input_top;
+       input_bottom = pDevice->pbuttonInformation->input_bottom;
+
+       if (!count || (this == NULL))
+               return -EINVAL;
+
+       if (!strncmp(buf, "reset", 5) || !strncmp(buf, "1", 1))
+               write_register(this, SX932x_STAT2_REG, 0x0F);
+
+       input_report_abs(input_top, ABS_DISTANCE, 0);
+       input_sync(input_top);
+       input_report_abs(input_bottom, ABS_DISTANCE, 0);
+       input_sync(input_bottom);
+
+       return count;
+}
+
+static CLASS_ATTR_RW(reset);
+
+static ssize_t enable_show(struct class *class,
+               struct class_attribute *attr,
+               char *buf)
+{
+       return snprintf(buf, 8, "%d\n", mEnabled);
+}
+
+static ssize_t enable_store(struct class *class,
+               struct class_attribute *attr,
+               const char *buf, size_t count)
+{
+       psx93XX_t this = sx9325_sar_ptr;
+       psx9325_t pDevice = NULL;
+       struct input_dev *input_top = NULL;
+       struct input_dev *input_bottom = NULL;
+
+       pDevice = this->pDevice;
+       input_top = pDevice->pbuttonInformation->input_top;
+       input_bottom = pDevice->pbuttonInformation->input_bottom;
+
+       if (!count || (this == NULL))
+               return -EINVAL;
+
+       if ((!strncmp(buf, "1", 1)) && (mEnabled == 0)) {
+               LOG_INFO("enable cap sensor\n");
+               initialize(this);
+
+               input_report_abs(input_top, ABS_DISTANCE, 0);
+               input_sync(input_top);
+               input_report_abs(input_bottom, ABS_DISTANCE, 0);
+               input_sync(input_bottom);
+               mEnabled = 1;
+       } else if ((!strncmp(buf, "0", 1)) && (mEnabled == 1)) {
+               LOG_INFO("disable cap sensor\n");
+
+               write_register(this, SX932x_CTRL1_REG, 0x10);
+               write_register(this, SX932x_IRQ_ENABLE_REG, 0x00);
+
+               input_report_abs(input_top, ABS_DISTANCE, -1);
+               input_sync(input_top);
+               input_report_abs(input_bottom, ABS_DISTANCE, -1);
+               input_sync(input_bottom);
+               mEnabled = 0;
+       } else {
+               LOG_ERR("unknown enable symbol\n");
+       }
+
+       return count;
+}
+
+#ifdef USE_SENSORS_CLASS
+static int capsensor_set_enable(struct sensors_classdev *sensors_cdev,
+                               unsigned int enable)
+{
+       psx93XX_t this = sx9325_sar_ptr;
+       psx9325_t pDevice = NULL;
+       struct input_dev *input_top = NULL;
+       struct input_dev *input_bottom = NULL;
+
+       pDevice = this->pDevice;
+       input_top = pDevice->pbuttonInformation->input_top;
+       input_bottom = pDevice->pbuttonInformation->input_bottom;
+
+       if ((enable == 1) && (mEnabled == 0)) {
+               LOG_INFO("enable cap sensor\n");
+               initialize(this);
+
+               input_report_abs(input_top, ABS_DISTANCE, 0);
+               input_sync(input_top);
+               input_report_abs(input_bottom, ABS_DISTANCE, 0);
+               input_sync(input_bottom);
+               mEnabled = 1;
+       } else if ((enable == 0) && (mEnabled == 1)) {
+               LOG_INFO("disable cap sensor\n");
+
+               write_register(this, SX932x_CTRL1_REG, 0x00);
+               write_register(this, SX932x_IRQ_ENABLE_REG, 0x00);
+
+               input_report_abs(input_top, ABS_DISTANCE, -1);
+               input_sync(input_top);
+               input_report_abs(input_bottom, ABS_DISTANCE, -1);
+               input_sync(input_bottom);
+               mEnabled = 0;
+       } else {
+               LOG_ERR("unknown enable symbol\n");
+       }
+
+       return 0;
+}
+#endif
+
+static CLASS_ATTR_RW(enable);
+static ssize_t reg_show(struct class *class,
+               struct class_attribute *attr,
+               char *buf)
+{
+    u16 i = 0;
+       u8 reg_value = 0;
+       u16 register_number = 0;
+       psx93XX_t this = sx9325_sar_ptr;
+       char *p = buf;
+
+       if (this->read_flag) {
+               this->read_flag = 0;
+               read_register(this, this->read_reg, &reg_value);
+               p += snprintf(p, PAGE_SIZE, "%02x\n", reg_value);
+               return (p-buf);
+       }
+
+       read_register(this, SX932x_IRQSTAT_REG, &reg_value);
+       p += snprintf(p, PAGE_SIZE, "IRQSTAT(0x%02x)=0x%02x\n",
+                       SX932x_IRQSTAT_REG, reg_value);
+
+       read_register(this, SX932x_STAT0_REG, &reg_value);
+       p += snprintf(p, PAGE_SIZE, "STAT0(0x%02x)=0x%02x\n",
+                       SX932x_STAT0_REG, reg_value);
+
+       read_register(this, SX932x_STAT1_REG, &reg_value);
+       p += snprintf(p, PAGE_SIZE, "STAT1(0x%02x)=0x%02x\n",
+                       SX932x_STAT1_REG, reg_value);
+
+       read_register(this, SX932x_STAT2_REG, &reg_value);
+       p += snprintf(p, PAGE_SIZE, "STAT2(0x%02x)=0x%02x\n",
+                       SX932x_STAT2_REG, reg_value);
+
+       read_register(this, SX932x_STAT3_REG, &reg_value);
+       p += snprintf(p, PAGE_SIZE, "STAT3(0x%02x)=0x%02x\n",
+                       SX932x_STAT3_REG, reg_value);
+
+       register_number = sizeof(sx9325_i2c_reg_setup)/sizeof(smtc_reg_data_t);
+
+       for (i = 0; i < register_number; i++)
+       {
+               read_register(this, sx9325_i2c_reg_setup[i].reg, &reg_value);
+               p += snprintf(p, PAGE_SIZE, "ENABLE(0x%02x)=0x%02x\n",
+                       sx9325_i2c_reg_setup[i].reg, reg_value);
+       }
+
+       read_register(this, SX932x_CPSRD, &reg_value);
+       p += snprintf(p, PAGE_SIZE, "CPSRD(0x%02x)=0x%02x\n",
+                       SX932x_CPSRD, reg_value);
+
+       read_register(this, SX932x_USEMSB, &reg_value);
+       p += snprintf(p, PAGE_SIZE, "USEMSB(0x%02x)=0x%02x\n",
+                       SX932x_USEMSB, reg_value);
+
+       read_register(this, SX932x_USELSB, &reg_value);
+       p += snprintf(p, PAGE_SIZE, "USELSB(0x%02x)=0x%02x\n",
+                       SX932x_USELSB, reg_value);
+
+       read_register(this, SX932x_AVGMSB, &reg_value);
+       p += snprintf(p, PAGE_SIZE, "AVGMSB(0x%02x)=0x%02x\n",
+                       SX932x_AVGMSB, reg_value);
+
+       read_register(this, SX932x_AVGLSB, &reg_value);
+       p += snprintf(p, PAGE_SIZE, "AVGLSB(0x%02x)=0x%02x\n",
+                       SX932x_AVGLSB, reg_value);
+
+       read_register(this, SX932x_DIFFMSB, &reg_value);
+       p += snprintf(p, PAGE_SIZE, "DIFFMSB(0x%02x)=0x%02x\n",
+                       SX932x_DIFFMSB, reg_value);
+
+       read_register(this, SX932x_DIFFLSB, &reg_value);
+       p += snprintf(p, PAGE_SIZE, "DIFFLSB(0x%02x)=0x%02x\n",
+                       SX932x_DIFFLSB, reg_value);
+
+       read_register(this, SX932x_OFFSETMSB, &reg_value);
+       p += snprintf(p, PAGE_SIZE, "OFFSETMSB(0x%02x)=0x%02x\n",
+                       SX932x_OFFSETMSB, reg_value);
+
+       read_register(this, SX932x_OFFSETLSB, &reg_value);
+       p += snprintf(p, PAGE_SIZE, "OFFSETLSB(0x%02x)=0x%02x\n",
+                       SX932x_OFFSETLSB, reg_value);
+
+       reg_value = gpio_get_value(this->board->irq_gpio);
+       p += snprintf(p, PAGE_SIZE, "NIRQ=%d\n", reg_value);
+
+       return (p-buf);
+}
+
+static ssize_t reg_store(struct class *class,
+               struct class_attribute *attr,
+               const char *buf, size_t count)
+{
+       psx93XX_t this = sx9325_sar_ptr;
+       unsigned int val, reg, opt;
+
+       if (strcmp("select_ch0\n", buf) == 0) {
+               write_register(this, SX932x_CPSRD, 0x00);
+       } else if (strcmp("select_ch1\n", buf) == 0) {
+               write_register(this, SX932x_CPSRD, 0x01);
+       } else if (strcmp("select_ch2\n", buf) == 0) {
+               write_register(this, SX932x_CPSRD, 0x02);
+       } else if (strcmp("calibrate\n", buf) == 0) {
+               write_register(this, SX932x_STAT2_REG, 0x0f);
+       } else if (sscanf(buf, "%x,%x,%x", &reg, &val, &opt) == 3) {
+               LOG_DBG("%s, read reg = 0x%02x\n", __func__, *(u8 *)&reg);
+               this->read_reg = *((u8 *)&reg);
+               this->read_flag = 1;
+       } else if (sscanf(buf, "%x,%x", &reg, &val) == 2) {
+               LOG_DBG("%s,reg = 0x%02x, val = 0x%02x\n",
+                               __func__, *(u8 *)&reg, *(u8 *)&val);
+               write_register(this, *((u8 *)&reg), *((u8 *)&val));
+       }
+
+       return count;
+}
+
+static CLASS_ATTR_RW(reg);
+
+static void ps_notify_callback_work(struct work_struct *work)
+{
+       psx93XX_t this = container_of(work, sx93XX_t, ps_notify_work);
+       psx9325_t pDevice = NULL;
+       struct input_dev *input_top = NULL;
+       struct input_dev *input_bottom = NULL;
+       int ret = 0;
+
+       pDevice = this->pDevice;
+       input_top = pDevice->pbuttonInformation->input_top;
+       input_bottom = pDevice->pbuttonInformation->input_bottom;
+
+       mutex_lock(&this->mutex);
+       if (mEnabled) {
+               LOG_INFO("Usb insert,going to force calibrate\n");
+               ret = write_register(this, SX932x_CTRL1_REG, 0x00);
+               if (ret < 0)
+                       LOG_ERR(" Usb insert,calibrate cap sensor failed\n");
+               msleep(100);
+               ret = write_register(this, SX932x_CTRL1_REG,
+                               this->board->cust_prox_ctrl0);
+               if (ret < 0)
+                       LOG_ERR(" Usb insert,enabel cap sensor failed\n");
+       }
+       mutex_unlock(&this->mutex);
+       input_report_abs(input_top, ABS_DISTANCE, 0);
+       input_sync(input_top);
+       input_report_abs(input_bottom, ABS_DISTANCE, 0);
+       input_sync(input_bottom);
+}
+
+static int ps_get_state(struct power_supply *psy, bool *present)
+{
+       union power_supply_propval pval = { 0 };
+       int retval;
+
+       retval = power_supply_get_property(psy, POWER_SUPPLY_PROP_PRESENT,
+                       &pval);
+       if (retval) {
+               LOG_ERR("%s psy get property failed\n", psy->desc->name);
+               return retval;
+       }
+       *present = (pval.intval) ? true : false;
+       LOG_INFO("%s is %s\n", psy->desc->name,
+                       (*present) ? "present" : "not present");
+       return 0;
+}
+
+static int ps_notify_callback(struct notifier_block *self,
+               unsigned long event, void *p)
+{
+       psx93XX_t this = container_of(self, sx93XX_t, ps_notif);
+       struct power_supply *psy = p;
+       bool present;
+       int retval;
+
+       if ((event == PSY_EVENT_PROP_ADDED || event == PSY_EVENT_PROP_CHANGED)
+                       && psy && psy->desc->get_property && psy->desc->name &&
+                       !strncmp(psy->desc->name, "usb", sizeof("usb"))) {
+               LOG_INFO("ps notification: event = %lu\n", event);
+               retval = ps_get_state(psy, &present);
+               if (retval) {
+                       LOG_ERR("psy get property failed\n");
+                       return retval;
+               }
+
+               if (event == PSY_EVENT_PROP_CHANGED) {
+                       if (this->ps_is_present == present) {
+                               LOG_INFO("ps present state not change\n");
+                               return 0;
+                       }
+               }
+               this->ps_is_present = present;
+               schedule_work(&this->ps_notify_work);
+       }
+
+       return 0;
+}
+
+#if defined(CONFIG_FB)
+static void fb_notify_resume_work(struct work_struct *work)
+{
+       psx93XX_t this = container_of(work, sx93XX_t, fb_notify_work);
+       psx9325_t pDevice = NULL;
+       struct input_dev *input_top = NULL;
+       struct input_dev *input_bottom = NULL;
+       int ret = 0;
+
+       pDevice = this->pDevice;
+       input_top = pDevice->pbuttonInformation->input_top;
+       input_bottom = pDevice->pbuttonInformation->input_bottom;
+
+       if (sx9325_debug_enable)
+               LOG_INFO("Lcd suspend/resume event,going to force reset\n");
+       ret = write_register(this, SX932x_STAT2_REG, 0x0f);
+       if (ret < 0)
+               LOG_ERR(" Lcd suspend/resume,reset cap sensor failed\n");
+}
+
+static int fb_notifier_callback(struct notifier_block *self,
+                               unsigned long event, void *data)
+{
+       struct fb_event *evdata = data;
+       int *blank;
+       psx93XX_t this = container_of(self, sx93XX_t, fb_notif);
+
+       if ((event == FB_EVENT_BLANK) &&
+               evdata && evdata->data) {
+               blank = evdata->data;
+               if ((*blank == FB_BLANK_POWERDOWN)
+                       || (*blank == FB_BLANK_UNBLANK)) {
+                       if (sx9325_debug_enable)
+                               LOG_INFO("fb event = %lu blank = %d\n",
+                                event, *blank);
+                       schedule_work(&this->fb_notify_work);
+               }
+       }
+
+       return 0;
+}
+#endif
+
+static struct class capsense_class = {
+       .name                   = "capsense",
+       .owner                  = THIS_MODULE,
+};
+
+/**
+ * fn static int sx9325_probe(struct i2c_client *client, const struct i2c_device_id *id)
+ * brief Probe function
+ * param client pointer to i2c_client
+ * param id pointer to i2c_device_id
+ * return Whether probe was successful
+ */
+static int sx9325_probe(struct i2c_client *client,
+                       const struct i2c_device_id *id)
+{
+       psx93XX_t this = 0;
+       psx9325_t pDevice = 0;
+       psx9325_platform_data_t pplatData = 0;
+       int ret;
+       struct input_dev *input_top = NULL;
+       struct input_dev *input_bottom = NULL;
+       struct power_supply *psy = NULL;
+
+       LOG_INFO("sx9325_probe()\n");
+
+       /* detect if sx9325 exist or not */
+       if (sx9325_detect(client) == 0)
+               return -ENODEV;
+
+       pplatData = kzalloc(sizeof(pplatData), GFP_KERNEL);
+       sx9325_platform_data_of_init(client, pplatData);
+       client->dev.platform_data = pplatData;
+
+       if (!pplatData) {
+               LOG_ERR("platform data is required!\n");
+               return -EINVAL;
+       }
+
+       if (!i2c_check_functionality(client->adapter,
+                               I2C_FUNC_SMBUS_READ_WORD_DATA))
+               return -EIO;
+
+       /* create memory for main struct */
+       this = kzalloc(sizeof(sx93XX_t), GFP_KERNEL);
+       LOG_INFO("\t Initialized Main Memory: 0x%p\n", this);
+
+       if (this) {
+               /* In case we need to reinitialize data
+                * (e.q. if suspend reset device) */
+               this->init = initialize;
+               /* shortcut to read status of interrupt */
+               this->refreshStatus = read_regStat;
+               /* pointer to function from platform data to get pendown
+                * (1->NIRQ=0, 0->NIRQ=1) */
+               this->get_nirq_low = pplatData->get_is_nirq_low;
+               /* save irq in case we need to reference it */
+               this->irq = gpio_to_irq(client->irq);
+               /* do we need to create an irq timer after interrupt ? */
+               this->useIrqTimer = 0;
+               this->board = pplatData;
+               /* Setup function to call on corresponding reg irq source bit */
+               if (MAX_NUM_STATUS_BITS >= 8) {
+                       this->statusFunc[0] = 0; /* TXEN_STAT */
+                       this->statusFunc[1] = 0; /* UNUSED */
+                       this->statusFunc[2] = touchProcess; /* BODY/TABLE */
+                       this->statusFunc[3] = read_rawData; /* CONV_STAT */
+                       this->statusFunc[4] = 0; /* COMP_STAT */
+                       this->statusFunc[5] = touchProcess; /* RELEASE_STAT */
+                       this->statusFunc[6] = touchProcess; /* TOUCH_STAT  */
+                       this->statusFunc[7] = 0; /* RESET_STAT */
+               }
+
+               /* setup i2c communication */
+               this->bus = client;
+               i2c_set_clientdata(client, this);
+
+               /* record device struct */
+               this->pdev = &client->dev;
+
+               /* create memory for device specific struct */
+               this->pDevice = pDevice = kzalloc(sizeof(sx9325_t), GFP_KERNEL);
+               LOG_INFO("\t Initialized Device Specific Memory: 0x%p\n",
+                               pDevice);
+               sx9325_sar_ptr = this;
+               if (pDevice) {
+                       /* for accessing items in user data (e.g. calibrate) */
+                       ret = sysfs_create_group(&client->dev.kobj,
+                                                &sx9325_attr_group);
+
+
+                       /* Check if we hava a platform
+                        * initialization function to call*/
+                       if (pplatData->init_platform_hw)
+                               pplatData->init_platform_hw();
+
+                       /* Add Pointer to main platform data struct */
+                       pDevice->hw = pplatData;
+
+                       /* Initialize the button information
+                        * initialized with keycodes */
+                       pDevice->pbuttonInformation =
+                                                pplatData->pbuttonInformation;
+
+                       /* Create the input device */
+                       input_top = input_allocate_device();
+                       if (!input_top)
+                               return -ENOMEM;
+
+                       /* Set all the keycodes */
+                       __set_bit(EV_ABS, input_top->evbit);
+                       input_set_abs_params(input_top, ABS_DISTANCE,
+                                                                -1, 100, 0, 0);
+                       /* save the input pointer and finish initialization */
+                       pDevice->pbuttonInformation->input_top =
+                                                                input_top;
+                       input_top->name = "SX9325 Cap Touch top";
+                       if (input_register_device(input_top)) {
+                               LOG_ERR("add top cap touch unsuccess\n");
+                               return -ENOMEM;
+                       }
+                       /* Create the input device */
+                       input_bottom = input_allocate_device();
+                       if (!input_bottom)
+                               return -ENOMEM;
+                       /* Set all the keycodes */
+                       __set_bit(EV_ABS, input_bottom->evbit);
+                       input_set_abs_params(input_bottom, ABS_DISTANCE,
+                                                                -1, 100, 0, 0);
+                       /* save the input pointer and finish initialization */
+                       pDevice->pbuttonInformation->input_bottom =
+                                                                input_bottom;
+                       /* save the input pointer and finish initialization */
+                       input_bottom->name = "SX9325 Cap Touch bottom";
+                       if (input_register_device(input_bottom)) {
+                               LOG_ERR("add bottom cap touch unsuccess\n");
+                               return -ENOMEM;
+                       }
+               }
+
+               ret = class_register(&capsense_class);
+               if (ret < 0) {
+                       LOG_ERR("Create fsys class failed (%d)\n", ret);
+                       return ret;
+               }
+
+               ret = class_create_file(&capsense_class, &class_attr_reset);
+               if (ret < 0) {
+                       LOG_ERR("Create reset file failed (%d)\n", ret);
+                       return ret;
+               }
+
+               ret = class_create_file(&capsense_class, &class_attr_enable);
+               if (ret < 0) {
+                       LOG_ERR("Create enable file failed (%d)\n", ret);
+                       return ret;
+               }
+
+               ret = class_create_file(&capsense_class, &class_attr_reg);
+               if (ret < 0) {
+                       LOG_ERR("Create reg file failed (%d)\n", ret);
+                       return ret;
+               }
+
+#ifdef USE_SENSORS_CLASS
+               sensors_capsensor_top_cdev.sensors_enable =
+                                                       capsensor_set_enable;
+               sensors_capsensor_top_cdev.sensors_poll_delay = NULL;
+               ret = sensors_classdev_register(&input_top->dev,
+                                               &sensors_capsensor_top_cdev);
+               if (ret < 0)
+                       LOG_ERR("create top cap sensor_class  file \
+                                failed (%d)\n", ret);
+               sensors_capsensor_bottom_cdev.sensors_enable =
+                                                        capsensor_set_enable;
+               sensors_capsensor_bottom_cdev.sensors_poll_delay = NULL;
+               ret = sensors_classdev_register(&input_bottom->dev,
+                                       &sensors_capsensor_bottom_cdev);
+               if (ret < 0)
+                       LOG_ERR("create bottom cap sensor_class file \
+                                failed (%d)\n", ret);
+#endif
+               pplatData->cap_vdd = regulator_get(&client->dev, "cap_vdd");
+               if (IS_ERR(pplatData->cap_vdd)) {
+                       if (PTR_ERR(pplatData->cap_vdd) == -EPROBE_DEFER) {
+                               ret = PTR_ERR(pplatData->cap_vdd);
+                               goto err_vdd_defer;
+                       }
+                       LOG_ERR("%s: Failed to get regulator\n",
+                                       __func__);
+               } else {
+                       int error = regulator_enable(pplatData->cap_vdd);
+
+                       if (error) {
+                               regulator_put(pplatData->cap_vdd);
+                               LOG_ERR("%s: Error %d enable regulator\n",
+                                               __func__, error);
+                               return error;
+                       }
+                       pplatData->cap_vdd_en = true;
+                       LOG_INFO("cap_vdd regulator is %s\n",
+                               regulator_is_enabled(pplatData->cap_vdd) ?
+                               "on" : "off");
+               }
+#if 0
+               pplatData->cap_svdd = regulator_get(&client->dev, "cap_svdd");
+               if (!IS_ERR(pplatData->cap_svdd)) {
+                       ret = regulator_enable(pplatData->cap_svdd);
+                       if (ret) {
+                               regulator_put(pplatData->cap_svdd);
+                               LOG_ERR("Failed to enable cap_svdd\n");
+                               goto err_svdd_error;
+                       }
+                       pplatData->cap_svdd_en = true;
+                       LOG_INFO("cap_svdd regulator is %s\n",
+                               regulator_is_enabled(pplatData->cap_svdd) ?
+                               "on" : "off");
+               } else {
+                       ret = PTR_ERR(pplatData->cap_vdd);
+                       if (ret == -EPROBE_DEFER)
+                               goto err_svdd_error;
+               }
+#endif
+               sx93XX_sar_init(this);
+
+               write_register(this, SX932x_CTRL1_REG, 0x10);
+               write_register(this, SX932x_IRQ_ENABLE_REG, 0x00);
+               mEnabled = 0;
+
+               INIT_WORK(&this->ps_notify_work, ps_notify_callback_work);
+               this->ps_notif.notifier_call = ps_notify_callback;
+               ret = power_supply_reg_notifier(&this->ps_notif);
+               if (ret) {
+                       LOG_ERR(
+                               "Unable to register ps_notifier: %d\n", ret);
+                       goto free_ps_notifier;
+               }
+
+               psy = power_supply_get_by_name("usb");
+               if (psy) {
+                       ret = ps_get_state(psy, &this->ps_is_present);
+                       if (ret) {
+                               LOG_ERR(
+                                       "psy get property failed rc=%d\n",
+                                       ret);
+                               goto free_ps_notifier;
+                       }
+               }
+
+#if defined(CONFIG_FB)
+               INIT_WORK(&this->fb_notify_work, fb_notify_resume_work);
+               this->fb_notif.notifier_call = fb_notifier_callback;
+               ret = fb_register_client(&this->fb_notif);
+               if (ret) {
+                       LOG_ERR("Unable to register fb_notifier: %d\n", ret);
+                       goto free_fb_notifier;
+               }
+#endif
+               return 0;
+       }
+       return -ENOMEM;
+
+free_fb_notifier:
+       power_supply_unreg_notifier(&this->ps_notif);
+
+free_ps_notifier:
+       LOG_ERR("%s free ps notifier:.\n", __func__);
+       regulator_disable(pplatData->cap_svdd);
+       regulator_put(pplatData->cap_svdd);
+#if 0
+err_svdd_error:
+       LOG_ERR("%s svdd defer.\n", __func__);
+       regulator_disable(pplatData->cap_vdd);
+       regulator_put(pplatData->cap_vdd);
+#endif
+err_vdd_defer:
+       LOG_ERR("%s input free device.\n", __func__);
+       input_free_device(input_top);
+       input_free_device(input_bottom);
+
+       return ret;
+}
+
+/**
+ * fn static int sx9325_remove(struct i2c_client *client)
+ * brief Called when device is to be removed
+ * param client Pointer to i2c_client struct
+ * return Value from sx93XX_sar_remove()
+ */
+static int sx9325_remove(struct i2c_client *client)
+{
+       psx9325_platform_data_t pplatData = 0;
+       psx9325_t pDevice = 0;
+       psx93XX_t this = i2c_get_clientdata(client);
+
+       pDevice = this->pDevice;
+       if (this && pDevice) {
+#if defined(CONFIG_FB)
+               fb_unregister_client(&this->fb_notif);
+#endif
+               power_supply_unreg_notifier(&this->ps_notif);
+
+#ifdef USE_SENSORS_CLASS
+               sensors_classdev_unregister(&sensors_capsensor_top_cdev);
+               sensors_classdev_unregister(&sensors_capsensor_bottom_cdev);
+#endif
+               input_unregister_device(pDevice->pbuttonInformation->input_top);
+               input_unregister_device(
+                               pDevice->pbuttonInformation->input_bottom);
+
+               if (this->board->cap_svdd_en) {
+                       regulator_disable(this->board->cap_svdd);
+                       regulator_put(this->board->cap_svdd);
+               }
+
+               if (this->board->cap_vdd_en) {
+                       regulator_disable(this->board->cap_vdd);
+                       regulator_put(this->board->cap_vdd);
+               }
+#ifdef USE_SENSORS_CLASS
+               sensors_classdev_unregister(&sensors_capsensor_top_cdev);
+               sensors_classdev_unregister(&sensors_capsensor_bottom_cdev);
+#endif
+               sysfs_remove_group(&client->dev.kobj, &sx9325_attr_group);
+               pplatData = client->dev.platform_data;
+               if (pplatData && pplatData->exit_platform_hw)
+                       pplatData->exit_platform_hw();
+               kfree(this->pDevice);
+       }
+       return sx93XX_sar_remove(this);
+}
+
+#if defined(USE_KERNEL_SUSPEND)
+/*====================================================*/
+/***** Kernel Suspend *****/
+static int sx9325_suspend(struct device *dev, pm_message_t mesg)
+{
+       psx93XX_t this = dev_get_drvdata(dev);
+
+       sx9325_irq_disable(this);
+       return 0;
+}
+/***** Kernel Resume *****/
+static int sx9325_resume(struct device *dev)
+{
+       psx93XX_t this = dev_get_drvdata(dev);
+
+       sx9325_irq_enable(this);
+       return 0;
+}
+/*====================================================*/
+#endif
+
+#ifdef CONFIG_OF
+static const struct of_device_id sx9325_match_tbl[] = {
+       { .compatible = "semtech,sx9325" ,},
+       { },
+};
+#endif
+
+static struct i2c_device_id sx9325_idtable[] = {
+       { DRIVER_NAME, 0 },
+       { }
+};
+
+static struct i2c_driver sx9325_driver = {
+
+        .probe          = sx9325_probe,
+        .remove         = sx9325_remove,
+        .id_table       = sx9325_idtable,
+        .driver = {
+                .name   = DRIVER_NAME,
+                .owner  = THIS_MODULE,
+#if defined(USE_KERNEL_SUSPEND)
+                .suspend  = sx9325_suspend,
+                .resume   = sx9325_resume,
+#endif
+#ifdef CONFIG_OF
+               .of_match_table = sx9325_match_tbl,
+#endif
+        },
+
+};
+
+static int __init sx9325_init(void)
+{
+       int ret = 0;
+       ret = i2c_add_driver(&sx9325_driver);
+        if (ret) {
+                LOG_ERR("%s: failed to add i2c driver", __func__);
+                goto err_driver;
+        }
+
+        LOG_DBG("%s: finished\n", __func__);
+
+err_driver:
+        return ret;
+}
+static void __exit sx9325_exit(void)
+{
+       i2c_del_driver(&sx9325_driver);
+}
+
+#ifdef USE_THREADED_IRQ
+static void sx93XX_process_interrupt(psx93XX_t this, u8 nirqlow)
+{
+       int status = 0;
+       int counter = 0;
+
+       if (!this) {
+               LOG_ERR("sx93XX_worker_func, NULL sx93XX_t\n");
+               return;
+       }
+       /* since we are not in an interrupt don't need to disable irq. */
+       status = this->refreshStatus(this);
+       counter = -1;
+       if (sx9325_debug_enable)
+               LOG_DBG("Worker - Refresh Status %d\n", status);
+
+       while ((++counter) < MAX_NUM_STATUS_BITS) { /* counter start from MSB */
+               if (((status >> counter) & 0x01)
+                       && (this->statusFunc[counter])) {
+                       if (sx9325_debug_enable)
+                               LOG_DBG("Function %d Pointer Found. Calling\n"
+                                       ,counter);
+                       this->statusFunc[counter](this);
+               }
+       }
+       if (unlikely(this->useIrqTimer && nirqlow)) {
+               /* In case we need to send a timer for example on a touchscreen
+                * checking penup, perform this here
+                */
+               cancel_delayed_work(&this->dworker);
+               schedule_delayed_work(&this->dworker,
+                               msecs_to_jiffies(this->irqTimeout));
+               LOG_INFO("Schedule Irq timer");
+       }
+}
+
+
+static void sx93XX_worker_func(struct work_struct *work)
+{
+       psx93XX_t this = 0;
+
+       if (work) {
+               this = container_of(work, sx93XX_t, dworker.work);
+               if (!this) {
+                       LOG_ERR("sx93XX_worker_func, NULL sx93XX_t\n");
+                       return;
+               }
+               if ((!this->get_nirq_low)
+                       || (!this->get_nirq_low(this->board->irq_gpio))) {
+                       /* only run if nirq is high */
+                       sx93XX_process_interrupt(this, 0);
+               }
+       } else {
+               LOG_ERR("sx93XX_worker_func, NULL work_struct\n");
+       }
+}
+static irqreturn_t sx93XX_interrupt_thread(int irq, void *data)
+{
+       psx93XX_t this = 0;
+
+       this = data;
+
+       mutex_lock(&this->mutex);
+       if (sx9325_debug_enable)
+               LOG_DBG("sx93XX_irq\n");
+       if ((!this->get_nirq_low) || this->get_nirq_low(this->board->irq_gpio))
+               sx93XX_process_interrupt(this, 1);
+       else {
+               if (sx9325_debug_enable)
+                       LOG_DBG("sx93XX_irq - nirq read high\n");
+       }
+       mutex_unlock(&this->mutex);
+       return IRQ_HANDLED;
+}
+#else
+static void sx93XX_schedule_work(psx93XX_t this, unsigned long delay)
+{
+       unsigned long flags;
+
+       if (this) {
+               LOG_INFO("sx93XX_schedule_work()\n");
+               spin_lock_irqsave(&this->lock, flags);
+               /* Stop any pending penup queues */
+               cancel_delayed_work(&this->dworker);
+               /*
+                * after waiting for a delay, this put the job
+                * in the kernel-global workqueue.
+                * so no need to create new thread in work queue.
+                */
+               schedule_delayed_work(&this->dworker, delay);
+               spin_unlock_irqrestore(&this->lock, flags);
+       } else
+               LOG_ERR("sx93XX_schedule_work, NULL psx93XX_t\n");
+}
+
+static irqreturn_t sx93XX_irq(int irq, void *pvoid)
+{
+       psx93XX_t this = 0;
+
+       if (pvoid) {
+               this = (psx93XX_t)pvoid;
+               if (sx9325_debug_enable)
+                       LOG_DBG("sx93XX_irq\n");
+               if ((!this->get_nirq_low)
+                       || this->get_nirq_low(this->board->irq_gpio)) {
+                       if (sx9325_debug_enable)
+                               LOG_DBG("sx93XX_irq - Schedule Work\n");
+                       sx93XX_schedule_work(this, 0);
+               } else {
+                       if (sx9325_debug_enable)
+                               LOG_DBG("sx93XX_irq - nirq read high\n");
+               }
+       } else
+               LOG_ERR("sx93XX_irq, NULL pvoid\n");
+       return IRQ_HANDLED;
+}
+
+static void sx93XX_worker_func(struct work_struct *work)
+{
+       psx93XX_t this = 0;
+       int status = 0;
+       int counter = 0;
+       u8 nirqLow = 0;
+
+       if (work) {
+               this = container_of(work, sx93XX_t, dworker.work);
+
+               if (!this) {
+                       LOG_ERR("sx93XX_worker_func, NULL sx93XX_t\n");
+                       return;
+               }
+               if (unlikely(this->useIrqTimer)) {
+                       if ((!this->get_nirq_low)
+                               || this->get_nirq_low(this->board->irq_gpio))
+                               nirqLow = 1;
+               }
+               /* since we are not in an interrupt
+                * don't need to disable irq. */
+               status = this->refreshStatus(this);
+               counter = -1;
+               if (sx9325_debug_enable)
+                       LOG_DBG("Worker - Refresh Status %d\n", status);
+               /* counter start from MSB */
+               while ((++counter) < MAX_NUM_STATUS_BITS) {
+                       if (((status >> counter) & 0x01)
+                               && (this->statusFunc[counter])) {
+                               LOG_INFO("Function %d Pointer Found. Calling\n"
+                                        ,counter);
+                               this->statusFunc[counter](this);
+                       }
+               }
+               if (unlikely(this->useIrqTimer && nirqLow)) {
+                       /* Early models and if RATE=0 for newer models
+                        * require a penup timer;
+                        * Queue up the function again for checking on penup */
+                       sx93XX_schedule_work(this,
+                                       msecs_to_jiffies(this->irqTimeout));
+               }
+       } else {
+               LOG_ERR("sx93XX_worker_func, NULL work_struct\n");
+       }
+}
+#endif
+
+void sx9325_irq_disable(psx93XX_t this)
+{
+       if (this) {
+               write_register(this, SX932x_CTRL1_REG,
+                               this->board->cust_prox_ctrl0&0xdf);
+               if (sx9325_debug_enable)
+                       LOG_INFO("sx9325 suspend: disable irq!\n");
+               disable_irq(this->irq);
+       }
+}
+void sx9325_irq_enable(psx93XX_t this)
+{
+       if (this) {
+               if (sx9325_debug_enable)
+                       LOG_INFO("sx9325 resume: enable irq!\n");
+#ifdef USE_THREADED_IRQ
+               mutex_lock(&this->mutex);
+               /* Just in case need to reset any uncaught interrupts */
+               sx93XX_process_interrupt(this, 0);
+               mutex_unlock(&this->mutex);
+#else
+               sx93XX_schedule_work(this, 0);
+#endif
+               enable_irq(this->irq);
+               write_register(this, SX932x_CTRL1_REG,
+                               this->board->cust_prox_ctrl0|0x20);
+               LOG_INFO("sx9325 resume: end!\n");
+       }
+}
+
+int sx93XX_sar_init(psx93XX_t this)
+{
+       int err = 0;
+
+       if (this && this->pDevice) {
+#ifdef USE_THREADED_IRQ
+
+               /* initialize worker function */
+               INIT_DELAYED_WORK(&this->dworker, sx93XX_worker_func);
+
+
+               /* initialize mutex */
+               mutex_init(&this->mutex);
+               /* initailize interrupt reporting */
+               this->irq_disabled = 0;
+               err = request_threaded_irq(this->irq, NULL,
+                               sx93XX_interrupt_thread,
+                               IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
+                               this->pdev->driver->name,
+                               this);
+#else
+               /* initialize spin lock */
+               spin_lock_init(&this->lock);
+
+               /* initialize worker function */
+               INIT_DELAYED_WORK(&this->dworker, sx93XX_worker_func);
+
+               /* initailize interrupt reporting */
+               this->irq_disabled = 0;
+               err = request_irq(this->irq, sx93XX_irq, IRQF_TRIGGER_FALLING,
+                               this->pdev->driver->name, this);
+#endif
+               if (err) {
+                       LOG_ERR("irq %d busy?\n", this->irq);
+                       return err;
+               }
+#ifdef USE_THREADED_IRQ
+               LOG_INFO("registered with threaded irq (%d)\n", this->irq);
+#else
+               LOG_INFO("registered with irq (%d)\n", this->irq);
+#endif
+               /* call init function pointer:
+                * this should initialize all registers */
+               if (this->init)
+                       return this->init(this);
+               LOG_ERR("No init function!!!!\n");
+       }
+       return -ENOMEM;
+}
+
+int sx93XX_sar_remove(psx93XX_t this)
+{
+       if (this) {
+               /* Cancel the Worker Func */
+               cancel_delayed_work_sync(&this->dworker);
+               free_irq(this->irq, this);
+               kfree(this);
+               return 0;
+       }
+       return -ENOMEM;
+}
+module_init(sx9325_init);
+module_exit(sx9325_exit);
+
+MODULE_AUTHOR("Semtech Corp. (http://www.semtech.com/)");
+MODULE_DESCRIPTION("SX9325 Capacitive Touch Controller Driver");
+MODULE_LICENSE("GPL");
+MODULE_VERSION("0.1");
diff --git a/drivers/input/misc/sx9325_sar.h b/drivers/input/misc/sx9325_sar.h
new file mode 100755 (executable)
index 0000000..d8d351d
--- /dev/null
@@ -0,0 +1,571 @@
+/*
+ * 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.
+ */
+#ifndef SX9325_TRIPLE_H
+#define SX9325_TRIPLE_H
+
+#include <linux/device.h>
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+#include <linux/sensors.h>
+#include <linux/regulator/consumer.h>
+/*
+ *  I2C Registers
+ */
+
+#define SX932x_IRQSTAT_REG             0x00
+#define SX932x_STAT0_REG               0x01
+#define SX932x_STAT1_REG               0x02
+#define SX932x_STAT2_REG               0x03
+#define SX932x_STAT3_REG               0x04
+#define SX932x_IRQ_ENABLE_REG  0x05
+#define SX932x_IRQCFG0_REG             0x06
+#define SX932x_IRQCFG1_REG             0x07
+#define SX932x_IRQCFG2_REG             0x08
+/*
+ *-General control
+ */
+#define SX932x_CTRL0_REG               0x10
+#define SX932x_CTRL1_REG               0x11
+#define SX932x_I2CADDR_REG             0x14
+#define SX932x_CLKSPRD                 0x15
+/*
+ *-AFE Control
+ */
+#define SX932x_AFE_CTRL0_REG   0x20
+#define SX932x_AFE_CTRL1_REG   0x21
+#define SX932x_AFE_CTRL2_REG   0x22
+#define SX932x_AFE_CTRL3_REG   0x23
+#define SX932x_AFE_CTRL4_REG   0x24
+#define SX932x_AFE_CTRL5_REG   0x25
+#define SX932x_AFE_CTRL6_REG   0x26
+#define SX932x_AFE_CTRL7_REG   0x27
+#define SX932x_AFE_PH0_REG             0x28
+#define SX932x_AFE_PH1_REG             0x29
+#define SX932x_AFE_PH2_REG             0x2A
+#define SX932x_AFE_PH3_REG             0x2B
+#define SX932x_AFE_CTRL8               0x2C
+#define SX932x_AFE_CTRL9               0x2D
+/*
+ *-Main Digital Processing (Prox) control
+ */
+#define SX932x_PROX_CTRL0_REG  0x30
+#define SX932x_PROX_CTRL1_REG  0x31
+#define SX932x_PROX_CTRL2_REG  0x32
+#define SX932x_PROX_CTRL3_REG  0x33
+#define SX932x_PROX_CTRL4_REG  0x34
+#define SX932x_PROX_CTRL5_REG  0x35
+#define SX932x_PROX_CTRL6_REG  0x36
+#define SX932x_PROX_CTRL7_REG  0x37
+/*
+ *-Advanced Digital Processing control
+ */
+#define SX932x_ADV_CTRL0_REG   0x40
+#define SX932x_ADV_CTRL1_REG   0x41
+#define SX932x_ADV_CTRL2_REG   0x42
+#define SX932x_ADV_CTRL3_REG   0x43
+#define SX932x_ADV_CTRL4_REG   0x44
+#define SX932x_ADV_CTRL5_REG   0x45
+#define SX932x_ADV_CTRL6_REG   0x46
+#define SX932x_ADV_CTRL7_REG   0x47
+#define SX932x_ADV_CTRL8_REG   0x48
+#define SX932x_ADV_CTRL9_REG   0x49
+#define SX932x_ADV_CTRL10_REG  0x4A
+#define SX932x_ADV_CTRL11_REG  0x4B
+#define SX932x_ADV_CTRL12_REG  0x4C
+#define SX932x_ADV_CTRL13_REG  0x4D
+#define SX932x_ADV_CTRL14_REG  0x4E
+#define SX932x_ADV_CTRL15_REG  0x4F
+#define SX932x_ADV_CTRL16_REG  0x50
+#define SX932x_ADV_CTRL17_REG  0x51
+#define SX932x_ADV_CTRL18_REG  0x52
+#define SX932x_ADV_CTRL19_REG  0x53
+#define SX932x_ADV_CTRL20_REG  0x54
+/*      Sensor Readback */
+#define SX932x_CPSRD                   0x60
+#define SX932x_USEMSB                  0x61
+#define SX932x_USELSB                  0x62
+#define SX932x_AVGMSB                  0x63
+#define SX932x_AVGLSB                  0x64
+#define SX932x_DIFFMSB                 0x65
+#define SX932x_DIFFLSB                 0x66
+#define SX932x_OFFSETMSB               0x67
+#define SX932x_OFFSETLSB               0x68
+#define SX932x_SARMSB                  0x69
+#define SX932x_SARLSB                  0x6A
+
+#define SX932x_SOFTRESET_REG   0x9F
+#define SX932x_WHOAMI_REG              0xFA
+#define SX932x_REV_REG                 0xFB
+
+/*      IrqStat 0:Inactive 1:Active     */
+#define SX932x_IRQSTAT_RESET_FLAG              0x80
+#define SX932x_IRQSTAT_TOUCH_FLAG              0x40
+#define SX932x_IRQSTAT_RELEASE_FLAG            0x20
+#define SX932x_IRQSTAT_COMPDONE_FLAG   0x10
+#define SX932x_IRQSTAT_CONV_FLAG               0x08
+#define SX932x_IRQSTAT_PROG2_FLAG              0x04
+#define SX932x_IRQSTAT_PROG1_FLAG              0x02
+#define SX932x_IRQSTAT_PROG0_FLAG              0x01
+
+
+/* RegStat0  */
+#define SX932x_PROXSTAT_PH3_FLAG               0x08
+#define SX932x_PROXSTAT_PH2_FLAG               0x04
+#define SX932x_PROXSTAT_PH1_FLAG               0x02
+#define SX932x_PROXSTAT_PH0_FLAG               0x01
+
+/*      SoftReset */
+#define SX932x_SOFTRESET                               0xDE
+#define SX932x_WHOAMI_VALUE                            0x22
+#define SX932x_REV_VALUE                               0x22
+
+
+/* CpsStat  */
+#define SX932x_TCHCMPSTAT_TCHCOMB_FLAG    0x88
+/* enable body stat */
+#define SX932x_TCHCMPSTAT_TCHSTAT2_FLAG   0x44
+/* enable body stat */
+#define SX932x_TCHCMPSTAT_TCHSTAT1_FLAG   0x22
+/* enable body stat */
+#define SX932x_TCHCMPSTAT_TCHSTAT0_FLAG   0x11
+
+
+
+/* useful channel number */
+#define USE_CHANNEL_NUM 3
+
+/* default settings */
+/* Channel enable: CS0:1,CS1:2,CS2:4,COMB:8
+ * Defines the Active scan period :
+ * 0000: Min (no idle time)
+ * 0001: 15ms
+ * 0010: 30 ms (Typ.)
+ * 0011: 45 ms
+ * 0100: 60 ms
+ * 0101: 90 ms
+ * 0110: 120 ms
+ * 0111: 200 ms
+ * 1000: 400 ms
+ * 1001: 600 ms
+ * 1010: 800 ms
+ * 1011: 1 s
+ * 1100: 2 s
+ * 1101: 3 s
+ * 1110: 4 s
+ * 1111: 5 s
+ */
+#define DUMMY_USE_CHANNEL      0x1
+#define DUMMY_SCAN_PERIOD      0x2
+#define DUMMY_RAW_DATA_CHANNEL 0x00
+
+/* Cap sensor report key, including cs0, cs1, cs2 and comb */
+#define KEY_CAP_CS0            0x270
+#define KEY_CAP_CS1            0x271
+#define KEY_CAP_CS2            0x272
+#define KEY_CAP_COMB           0x272
+
+/**************************************
+* define platform data
+*
+**************************************/
+struct smtc_reg_data {
+       unsigned char reg;
+       unsigned char val;
+};
+
+typedef struct smtc_reg_data smtc_reg_data_t;
+typedef struct smtc_reg_data *psmtc_reg_data_t;
+
+
+struct _buttonInfo {
+       /* The Key to send to the input */
+       int keycode;
+       /* Mask to look for on Touch Status */
+       int mask;
+       /* Current state of button. */
+       int state;
+};
+
+struct _totalButtonInformation {
+       struct _buttonInfo *buttons;
+       int buttonSize;
+       struct input_dev *input_top;
+       struct input_dev *input_bottom;
+};
+
+typedef struct _totalButtonInformation buttonInformation_t;
+typedef struct _totalButtonInformation *pbuttonInformation_t;
+
+/* Define Registers that need to be initialized to values different than
+ * default
+ */
+static struct smtc_reg_data sx9325_i2c_reg_setup[] = {
+/*Interrupt and config*/
+       {
+               .reg = SX932x_IRQ_ENABLE_REG,   //0x05
+               .val = 0x64,                                    // Enavle Close and Far -> enable compensation interrupt
+       },
+       {
+               .reg = SX932x_IRQCFG0_REG,              //0x06
+               .val = 0x00,                                    //
+       },
+       {
+               .reg = SX932x_IRQCFG1_REG,              //0x07
+               .val = 0x00,
+       },
+       {
+               .reg = SX932x_IRQCFG2_REG,              //0x08
+               .val = 0x00,                                    //Activ Low
+       },
+       //--------General control
+       {
+               .reg = SX932x_CTRL0_REG,        //0x10
+               .val = 0x09,       // Scanperiod : 100ms(10110)
+       },
+       {
+               .reg = SX932x_I2CADDR_REG,       //0x14
+               .val = 0x00,       //I2C Address : 0x28
+       },
+       {
+               .reg = SX932x_CLKSPRD,    //0x15
+               .val = 0x00,       //
+       },
+       //--------AFE Control
+       {
+               .reg = SX932x_AFE_CTRL0_REG,   //0x20
+               .val = 0x00,       // CSx pin during sleep mode : HZ
+       },
+       {
+               .reg = SX932x_AFE_CTRL1_REG,   //0x21
+               .val = 0x10,       //reserved
+       },
+       {
+               .reg = SX932x_AFE_CTRL2_REG,   //0x22
+               .val = 0x00,       //reserved
+       },
+       {
+               .reg = SX932x_AFE_CTRL3_REG,   //0x23
+               .val = 0x00,       //Analog Range(ph0/1) : Small
+       },
+       {
+               .reg = SX932x_AFE_CTRL4_REG,   //0x24
+               .val = 0x44,       //Sampling Freq(ph0/1) : 83.33khz(01000), Resolution(ph0/1) : 128(100)
+       },
+       {
+               .reg = SX932x_AFE_CTRL5_REG,   //0x25
+               .val = 0x00,       //reserved
+       },
+       {
+               .reg = SX932x_AFE_CTRL6_REG,   //0x26
+               .val = 0x01,       //big//Analog Range(ph2/3) : Small
+       },
+       {
+               .reg = SX932x_AFE_CTRL7_REG,   //0x27
+               .val = 0x44,       //Sampling Freq(ph2/3) : 83.33khz(01000), Resolution(ph2/3) : 128(100)
+       },
+       {
+               .reg = SX932x_AFE_PH0_REG,       //0x28
+               .val = 0x01,//0x04,        // CS2:HZ CS1:Input CS0 :HZ
+       },
+       {
+               .reg = SX932x_AFE_PH1_REG,         //0x29
+               .val = 0x04,//0x10,        // CS2:Input CS1:HZ Shield CS0 :HZ
+       },
+       {
+               .reg = SX932x_AFE_PH2_REG,       //0x2A
+               .val = 0x10,//0x1B,        //CS2:HZ CS1:HZ CS0 :HZ
+       },
+       {
+               .reg = SX932x_AFE_PH3_REG,       //0x2B
+               .val = 0x00,       //CS2:HZ CS1:HZ CS0 :HZ
+       },
+       {
+               .reg = SX932x_AFE_CTRL8,        //0x2C
+               .val = 0x12,       // input register(kohm) 4(0010)
+       },
+       {
+               .reg = SX932x_AFE_CTRL9,        //0x2D
+               .val = 0x08,       // Analg gain : x1(1000)
+       },
+       /*--------PROX control*/
+       {
+               .reg = SX932x_PROX_CTRL0_REG,  //0x30
+               .val = 0x13,       // Digital Gain(ph0/1) : off(001) Digital Filter(ph0/1) : 1-1/2(001)
+       },
+       {
+               .reg = SX932x_PROX_CTRL1_REG,  //0x31
+               .val = 0x0a,       // Digital Gain(ph2/3) : off(001) Digital Filter(ph2/3) : 1-1/2(001)
+       },
+       {
+               .reg = SX932x_PROX_CTRL2_REG,  //0x32
+               .val = 0x08,       //AVGNEGTHRESH : 16384
+       },
+       {
+               .reg = SX932x_PROX_CTRL3_REG,  // 0x33
+               .val = 0x20,       //AVGPOSTHRESH : 16384
+       },
+       {
+               .reg = SX932x_PROX_CTRL4_REG,  //0x34
+               .val = 0x0a,       //AVGFREEZEDIS : on(0) ,AVGNEGFILT :1-1/2(001) ,AVGPOSFILT : 1-1/256(100)
+       },
+       {
+               .reg = SX932x_PROX_CTRL5_REG,  //0x35
+               .val = 0x0a,       //FARCOND: PROXDIFF < (THRESH.HYST), HYST : None, CLOSEDEB : off ,FARDEB : off
+       },
+       {
+               .reg = SX932x_PROX_CTRL6_REG,  //0x36
+               .val = 0x1e,       // Prox Theshold(ph0/1) : 200
+       },
+       {
+               .reg = SX932x_PROX_CTRL7_REG,  //0x37
+               .val = 0x15,       // Prox Theshold(ph2/3) : 200
+       },
+       /*Advanced control (defult)*/
+       {
+               .reg = SX932x_ADV_CTRL0_REG,
+               .val = 0x00,
+       },
+       {
+               .reg = SX932x_ADV_CTRL1_REG,
+               .val = 0x00,
+       },
+       {
+               .reg = SX932x_ADV_CTRL2_REG,
+               .val = 0x18,//0x10,
+       },
+       {
+               .reg = SX932x_ADV_CTRL3_REG,
+               .val = 0x2a,
+       },
+       {
+               .reg = SX932x_ADV_CTRL4_REG,
+               .val = 0x02,
+       },
+       {
+               .reg = SX932x_ADV_CTRL5_REG,
+               .val = 0x05,
+       },
+       {
+               .reg = SX932x_ADV_CTRL6_REG,
+               .val = 0x00,
+       },
+       {
+               .reg = SX932x_ADV_CTRL7_REG,
+               .val = 0x00,
+       },
+       {
+               .reg = SX932x_ADV_CTRL8_REG,
+               .val = 0x00,
+       },
+       {
+               .reg = SX932x_ADV_CTRL9_REG,
+               .val = 0x80,
+       },
+       {
+               .reg = SX932x_ADV_CTRL10_REG,
+               .val = 0x11,
+       },
+       {
+               .reg = SX932x_ADV_CTRL11_REG,
+               .val = 0x00,
+       },
+       {
+               .reg = SX932x_ADV_CTRL12_REG,
+               .val = 0x00,
+       },
+       {
+               .reg = SX932x_ADV_CTRL13_REG,
+               .val = 0x00,
+       },
+       {
+               .reg = SX932x_ADV_CTRL14_REG,
+               .val = 0x80,
+       },
+       {
+               .reg = SX932x_ADV_CTRL15_REG,
+               .val = 0x0C,
+       },
+       {
+               .reg = SX932x_ADV_CTRL16_REG,
+               .val = 0x00,
+       },
+       {
+               .reg = SX932x_ADV_CTRL17_REG,
+               .val = 0x00,
+       },
+       {
+               .reg = SX932x_ADV_CTRL18_REG,
+               .val = 0x00,
+       },
+       {
+               .reg = SX932x_ADV_CTRL19_REG,
+               .val = 0xF0,
+       },
+       {
+               .reg = SX932x_ADV_CTRL20_REG,
+               .val = 0xF0,
+       },
+       /*Sensor enable*/
+       {
+               .reg = SX932x_CTRL1_REG,        //0x11
+               .val = 0x24,       //enable PH2
+       },
+};
+
+
+
+
+static struct _buttonInfo psmtcButtons[] = {
+       {
+               .keycode = KEY_CAP_CS0,
+               .mask = SX932x_TCHCMPSTAT_TCHSTAT0_FLAG,
+       },
+       {
+               .keycode = KEY_CAP_CS1,
+               .mask = SX932x_TCHCMPSTAT_TCHSTAT1_FLAG,
+       },
+       {
+               .keycode = KEY_CAP_CS2,
+               .mask = SX932x_TCHCMPSTAT_TCHSTAT2_FLAG,
+       },
+       {
+               .keycode = KEY_CAP_COMB,
+               .mask = SX932x_TCHCMPSTAT_TCHCOMB_FLAG,
+       },
+};
+
+struct sx9325_platform_data {
+       int i2c_reg_num;
+       struct smtc_reg_data *pi2c_reg;
+       struct regulator *cap_vdd;
+       struct regulator *cap_svdd;
+       bool cap_vdd_en;
+       bool cap_svdd_en;
+       unsigned irq_gpio;
+       /* used for custom setting for channel and scan period */
+       u32 cust_prox_ctrl0;
+       u32 cust_raw_data_channel;
+       int cap_channel_top;
+       int cap_channel_bottom;
+       pbuttonInformation_t pbuttonInformation;
+
+       int (*get_is_nirq_low)(unsigned irq_gpio);
+       int (*init_platform_hw)(void);
+       void (*exit_platform_hw)(void);
+};
+typedef struct sx9325_platform_data sx9325_platform_data_t;
+typedef struct sx9325_platform_data *psx9325_platform_data_t;
+
+#ifdef USE_SENSORS_CLASS
+static struct sensors_classdev sensors_capsensor_top_cdev = {
+       .name = "capsense_top",
+       .vendor = "semtech",
+       .version = 1,
+       .type = SENSOR_TYPE_MOTO_CAPSENSE,
+       .max_range = "5",
+       .resolution = "5.0",
+       .sensor_power = "3",
+       .min_delay = 0, /* in microseconds */
+       .fifo_reserved_event_count = 0,
+       .fifo_max_event_count = 0,
+       .enabled = 0,
+       .delay_msec = 100,
+       .sensors_enable = NULL,
+       .sensors_poll_delay = NULL,
+};
+static struct sensors_classdev sensors_capsensor_bottom_cdev = {
+       .name = "capsense_bottom",
+       .vendor = "semtech",
+       .version = 1,
+       .type = SENSOR_TYPE_MOTO_CAPSENSE,
+       .max_range = "5",
+       .resolution = "5.0",
+       .sensor_power = "3",
+       .min_delay = 0, /* in microseconds */
+       .fifo_reserved_event_count = 0,
+       .fifo_max_event_count = 0,
+       .enabled = 0,
+       .delay_msec = 100,
+       .sensors_enable = NULL,
+       .sensors_poll_delay = NULL,
+};
+#endif
+/***************************************
+* define data struct/interrupt
+* @pdev: pdev common device struction for linux
+* @dworker: work struct for worker function
+* @board: constant pointer to platform data
+* @mutex: mutex for interrupt process
+* @lock: Spin Lock used for nirq worker function
+* @bus: either i2c_client or spi_client
+* @pDevice: device specific struct pointer
+*@read_flag : used for dump specified register
+* @irq: irq number used
+* @irqTimeout: msecs only set if useIrqTimer is true
+* @irq_disabled: whether irq should be ignored
+* @irq_gpio: irq gpio number
+* @useIrqTimer: older models need irq timer for pen up cases
+* @read_reg: record reg address which want to read
+*@cust_prox_ctrl0 : used for custom setting for channel and scan period
+* @init: (re)initialize device
+* @refreshStatus: read register status
+* @get_nirq_low: get whether nirq is low (platform data)
+* @statusFunc: array of functions to call for corresponding status bit
+***************************************/
+#define USE_THREADED_IRQ
+
+#define MAX_NUM_STATUS_BITS (8)
+
+typedef struct sx93XX sx93XX_t, *psx93XX_t;
+struct sx93XX {
+       struct device *pdev;
+       struct delayed_work dworker;
+       struct sx9325_platform_data *board;
+#if defined(USE_THREADED_IRQ)
+       struct mutex mutex;
+#else
+       spinlock_t      lock;
+#endif
+       void *bus;
+       void *pDevice;
+       int read_flag;
+       int irq;
+       int irqTimeout;
+       char irq_disabled;
+       /* whether irq should be ignored..
+        * cases if enable/disable irq is not used
+        * or does not work properly */
+       u8 useIrqTimer;
+       u8 read_reg;
+
+       struct work_struct ps_notify_work;
+       struct notifier_block ps_notif;
+       bool ps_is_present;
+
+#if defined(CONFIG_FB)
+       struct work_struct fb_notify_work;
+       struct notifier_block fb_notif;
+#endif
+
+       /* Function Pointers */
+       int (*init)(psx93XX_t this);
+       /* since we are trying to avoid knowing registers, create a pointer to a
+        * common read register which would be to read what the interrupt source
+        * is from
+        */
+       int (*refreshStatus)(psx93XX_t this);
+       int (*get_nirq_low)(unsigned irq_gpio);
+
+       void (*statusFunc[MAX_NUM_STATUS_BITS])(psx93XX_t this);
+
+};
+
+void sx9325_irq_disable(psx93XX_t this);
+void sx9325_irq_enable(psx93XX_t this);
+int sx93XX_sar_init(psx93XX_t this);
+int sx93XX_sar_remove(psx93XX_t this);
+
+#endif
diff --git a/drivers/input/misc/sx932x.c b/drivers/input/misc/sx932x.c
deleted file mode 100755 (executable)
index ea49900..0000000
+++ /dev/null
@@ -1,971 +0,0 @@
-/*! \file sx932x.c\r
- * \brief  SX9320 Driver\r
- *\r
- * Driver for the SX9320\r
- * Copyright (c) 2011 Semtech Corp\r
- *\r
- *  This program is free software; you can redistribute it and/or modify\r
- *  it under the terms of the GNU General Public License version 2 as\r
- *  published by the Free Software Foundation.\r
- */\r
-#define DEBUG\r
-#define DRIVER_NAME "sx932x"\r
-\r
-#define MAX_WRITE_ARRAY_SIZE 32\r
-\r
-#include <linux/module.h>\r
-#include <linux/slab.h>\r
-#include <linux/i2c.h>\r
-#include <linux/init.h>\r
-#include <linux/delay.h>\r
-#include <linux/input.h>\r
-#include <linux/fs.h>\r
-#include <linux/device.h>\r
-#include <linux/interrupt.h>\r
-#include <linux/syscalls.h>\r
-#include <linux/wakelock.h>\r
-#include <linux/uaccess.h>\r
-#include <linux/sort.h>\r
-#include <linux/gpio.h>\r
-#include <linux/of_gpio.h>\r
-#include <linux/regulator/consumer.h>\r
-#include "sx932x.h"    /* main struct, interrupt,init,pointers */\r
-\r
-#define IDLE                   0\r
-#define ACTIVE                 1\r
-\r
-#define SX932x_NIRQ            34\r
-\r
-#define MAIN_SENSOR            1 //CS1\r
-\r
-/* Failer Index */\r
-#define SX932x_ID_ERROR        1\r
-#define SX932x_NIRQ_ERROR      2\r
-#define SX932x_CONN_ERROR      3\r
-#define SX932x_I2C_ERROR       4\r
-\r
-#define PROXOFFSET_LOW                 1500\r
-\r
-#define SX932x_ANALOG_GAIN             1\r
-#define SX932x_DIGITAL_GAIN            1\r
-#define SX932x_ANALOG_RANGE            2.65\r
-\r
-#define        TOUCH_CHECK_REF_AMB      0 // 44523\r
-#define        TOUCH_CHECK_SLOPE        0 // 50\r
-#define        TOUCH_CHECK_MAIN_AMB     0 // 151282\r
-\r
-/*! \struct sx932x\r
- * Specialized struct containing input event data, platform data, and\r
- * last cap state read if needed.\r
- */\r
-typedef struct sx932x\r
-{\r
-       pbuttonInformation_t pbuttonInformation;\r
-       psx932x_platform_data_t hw;             /* specific platform data settings */\r
-} sx932x_t, *psx932x_t;\r
-\r
-static int irq_gpio_num;\r
-\r
-/*! \fn static int write_register(psx93XX_t this, u8 address, u8 value)\r
- * \brief Sends a write register to the device\r
- * \param this Pointer to main parent struct\r
- * \param address 8-bit register address\r
- * \param value   8-bit register value to write to address\r
- * \return Value from i2c_master_send\r
- */\r
-\r
-static int write_register(psx93XX_t this, u8 address, u8 value)\r
-{\r
-       struct i2c_client *i2c = 0;\r
-       char buffer[2];\r
-       int returnValue = 0;\r
-\r
-       buffer[0] = address;\r
-       buffer[1] = value;\r
-       returnValue = -ENOMEM;\r
-\r
-       if (this && this->bus) {\r
-               i2c = this->bus;\r
-               returnValue = i2c_master_send(i2c,buffer,2);\r
-               #ifdef DEBUG\r
-               dev_info(&i2c->dev,"write_register Address: 0x%x Value: 0x%x Return: %d\n",\r
-                                                                                                               address,value,returnValue);\r
-               #endif\r
-       }\r
-       return returnValue;\r
-}\r
-\r
-/*! \fn static int read_register(psx93XX_t this, u8 address, u8 *value)\r
-* \brief Reads a register's value from the device\r
-* \param this Pointer to main parent struct\r
-* \param address 8-Bit address to read from\r
-* \param value Pointer to 8-bit value to save register value to\r
-* \return Value from i2c_smbus_read_byte_data if < 0. else 0\r
-*/\r
-static int read_register(psx93XX_t this, u8 address, u8 *value)\r
-{\r
-       struct i2c_client *i2c = 0;\r
-       s32 returnValue = 0;\r
-\r
-       if (this && value && this->bus) {\r
-               i2c = this->bus;\r
-               dev_info(&i2c->dev, "read_register Address:i2c:%s 0x%x Return: 0x%x\n",this->bus,\r
-                                                                                                               address,returnValue);\r
-               returnValue = i2c_smbus_read_byte_data(i2c,address);\r
-\r
-               #ifdef DEBUG\r
-               dev_info(&i2c->dev, "read_register Address: 0x%x Return: 0x%x\n",\r
-                                                                                                               address,returnValue);\r
-               #endif\r
-\r
-               if (returnValue >= 0) {\r
-                       *value = returnValue;\r
-                       return 0;\r
-               }\r
-               else {\r
-                       return returnValue;\r
-               }\r
-       }\r
-       return -ENOMEM;\r
-}\r
-\r
-//static int sx9320_set_mode(psx93XX_t this, unsigned char mode);\r
-\r
-/*! \fn static int read_regStat(psx93XX_t this)\r
- * \brief Shortcut to read what caused interrupt.\r
- * \details This is to keep the drivers a unified\r
- * function that will read whatever register(s)\r
- * provide information on why the interrupt was caused.\r
- * \param this Pointer to main parent struct\r
- * \return If successful, Value of bit(s) that cause interrupt, else 0\r
- */\r
-static int read_regStat(psx93XX_t this)\r
-{\r
-       u8 data = 0;\r
-       if (this) {\r
-               if (read_register(this,SX932x_IRQSTAT_REG,&data) == 0)\r
-               return (data & 0x00FF);\r
-       }\r
-       return 0;\r
-}\r
-\r
-/*********************************************************************/\r
-/*! \brief Perform a manual offset calibration\r
-* \param this Pointer to main parent struct \r
-* \return Value return value from the write register\r
- */\r
-static int manual_offset_calibration(psx93XX_t this)\r
-{\r
-       s32 returnValue = 0;\r
-       returnValue = write_register(this,SX932x_STAT2_REG,0x0F);\r
-       return returnValue;\r
-}\r
-/*! \brief sysfs show function for manual calibration which currently just\r
- * returns register value.\r
- */\r
-static ssize_t manual_offset_calibration_show(struct device *dev,\r
-                                                               struct device_attribute *attr, char *buf)\r
-{\r
-       u8 reg_value = 0;\r
-       psx93XX_t this = dev_get_drvdata(dev);\r
-\r
-       dev_info(this->pdev, "Reading IRQSTAT_REG\n");\r
-       read_register(this,SX932x_IRQSTAT_REG,&reg_value);\r
-       return sprintf(buf, "%d\n", reg_value);\r
-}\r
-\r
-/*! \brief sysfs store function for manual calibration\r
- */\r
-static ssize_t manual_offset_calibration_store(struct device *dev,\r
-                       struct device_attribute *attr,const char *buf, size_t count)\r
-{\r
-       psx93XX_t this = dev_get_drvdata(dev);\r
-       unsigned long val;\r
-       if (kstrtoul(buf, 0, &val))\r
-       return -EINVAL;\r
-       if (val) {\r
-               dev_info( this->pdev, "Performing manual_offset_calibration()\n");\r
-               manual_offset_calibration(this);\r
-       }\r
-       return count;\r
-}\r
-\r
-static int sx932x_Hardware_Check(psx93XX_t this)\r
-{\r
-       int ret;\r
-       u8 failcode;\r
-       u8 loop = 0;\r
-       this->failStatusCode = 0;\r
-\r
-       //Check th IRQ Status\r
-       while(this->get_nirq_low && this->get_nirq_low()){\r
-               read_regStat(this);\r
-               msleep(100);\r
-               if(++loop >10){\r
-                       this->failStatusCode = SX932x_NIRQ_ERROR;\r
-                       break;\r
-               }\r
-       }\r
-\r
-       //Check I2C Connection\r
-       ret = read_register(this, SX932x_WHOAMI_REG, &failcode);\r
-       if(ret < 0){\r
-               this->failStatusCode = SX932x_I2C_ERROR;\r
-       }\r
-\r
-       if(failcode!= SX932x_WHOAMI_VALUE){\r
-               this->failStatusCode = SX932x_ID_ERROR;\r
-       }\r
-\r
-       dev_info(this->pdev, "sx932x failcode = 0x%x\n",this->failStatusCode);\r
-       return (int)this->failStatusCode;\r
-}\r
-\r
-\r
-/*********************************************************************/\r
-static int sx932x_global_variable_init(psx93XX_t this)\r
-{\r
-       this->irq_disabled = 0;\r
-       this->failStatusCode = 0;\r
-       this->reg_in_dts = true;\r
-       return 0;\r
-}\r
-\r
-static ssize_t sx932x_register_write_store(struct device *dev,\r
-                       struct device_attribute *attr, const char *buf, size_t count)\r
-{\r
-       int reg_address = 0, val = 0;\r
-       psx93XX_t this = dev_get_drvdata(dev);\r
-\r
-       if (sscanf(buf, "%x,%x", &reg_address, &val) != 2) {\r
-               pr_err("[SX9320]: %s - The number of data are wrong\n",__func__);\r
-               return -EINVAL;\r
-       }\r
-\r
-       write_register(this, (unsigned char)reg_address, (unsigned char)val);\r
-       pr_info("[SX9320]: %s - Register(0x%x) data(0x%x)\n",__func__, reg_address, val);\r
-\r
-       return count;\r
-}\r
-//read registers not include the advanced one\r
-static ssize_t sx932x_register_read_store(struct device *dev,\r
-                       struct device_attribute *attr, const char *buf, size_t count)\r
-{\r
-       u8 val=0;\r
-       int regist = 0;\r
-       psx93XX_t this = dev_get_drvdata(dev);\r
-\r
-       dev_info(this->pdev, "Reading register\n");\r
-\r
-       if (sscanf(buf, "%x", &regist) != 1) {\r
-               pr_err("[SX9320]: %s - The number of data are wrong\n",__func__);\r
-               return -EINVAL;\r
-       }\r
-       dev_info(this->pdev, "regist = 0x%x\n",regist);\r
-       read_register(this, regist, &val);\r
-       pr_info("[SX9320]: %s - Register(0x%2x) data(0x%2x)\n",__func__, regist, val);\r
-\r
-       return count;\r
-}\r
-\r
-static ssize_t sx932x_register_read_show(struct device *dev,\r
-                       struct device_attribute *attr,  char *buf)\r
-{\r
-       u8 val=0;\r
-       u8 val1=0;\r
-       psx93XX_t this = dev_get_drvdata(dev);\r
-\r
-       dev_info(this->pdev, "Reading register\n");\r
-       read_register(this, SX932x_DIFFMSB, &val);\r
-       read_register(this, SX932x_DIFFLSB, &val1);\r
-       dev_info(this->pdev,"[SX9320]: %s - Register(0x%2x) data(0x%2x)\n",__func__, SX932x_DIFFMSB, val);\r
-       dev_info(this->pdev,"[SX9320]: %s - Register(0x%2x) data(0x%2x)\n",__func__, SX932x_DIFFLSB, val1);\r
-       return sprintf(buf, "%x%x\n", val,val1);\r
-}\r
-static void read_rawData(psx93XX_t this)\r
-{\r
-       u8 msb=0, lsb=0;\r
-       u8 csx;\r
-       s32 useful;\r
-       s32 average;\r
-       s32 diff;\r
-       u16 offset;\r
-       if(this){\r
-               for(csx =0; csx<4; csx++){\r
-                       write_register(this,SX932x_CPSRD,csx);//here to check the CS1, also can read other channel\r
-                       read_register(this,SX932x_USEMSB,&msb);\r
-                       read_register(this,SX932x_USELSB,&lsb);\r
-                       useful = (s32)((msb << 8) | lsb);\r
-\r
-                       read_register(this,SX932x_AVGMSB,&msb);\r
-                       read_register(this,SX932x_AVGLSB,&lsb);\r
-                       average = (s32)((msb << 8) | lsb);\r
-\r
-                       read_register(this,SX932x_DIFFMSB,&msb);\r
-                       read_register(this,SX932x_DIFFLSB,&lsb);\r
-                       diff = (s32)((msb << 8) | lsb);\r
-\r
-                       read_register(this,SX932x_OFFSETMSB,&msb);\r
-                       read_register(this,SX932x_OFFSETLSB,&lsb);\r
-                       offset = (u16)((msb << 8) | lsb);\r
-                       if (useful > 32767)\r
-                               useful -= 65536;\r
-                       if (average > 32767)\r
-                               average -= 65536;\r
-                       if (diff > 32767)\r
-                               diff -= 65536;\r
-                       dev_info(this->pdev, " [CS: %d] Useful = %d Average = %d, DIFF = %d Offset = %d \n",csx,useful,average,diff,offset);\r
-               }\r
-       }\r
-}\r
-\r
-static ssize_t sx932x_raw_data_show(struct device *dev,\r
-                                               struct device_attribute *attr, char *buf)\r
-{\r
-       psx93XX_t this = dev_get_drvdata(dev);\r
-       read_rawData(this);\r
-       return 0;\r
-}\r
-\r
-static DEVICE_ATTR(manual_calibrate, 0664, manual_offset_calibration_show,manual_offset_calibration_store);\r
-static DEVICE_ATTR(register_write,  0664, NULL,sx932x_register_write_store);\r
-static DEVICE_ATTR(register_read,0664, sx932x_register_read_show,sx932x_register_read_store);\r
-static DEVICE_ATTR(raw_data,0664,sx932x_raw_data_show,NULL);\r
-static struct attribute *sx932x_attributes[] = {\r
-       &dev_attr_manual_calibrate.attr,\r
-       &dev_attr_register_write.attr,\r
-       &dev_attr_register_read.attr,\r
-       &dev_attr_raw_data.attr,\r
-       NULL,\r
-};\r
-static struct attribute_group sx932x_attr_group = {\r
-       .attrs = sx932x_attributes,\r
-};\r
-\r
-/****************************************************/\r
-/*! \brief  Initialize I2C config from platform data\r
- * \param this Pointer to main parent struct \r
- */\r
-static void sx932x_reg_init(psx93XX_t this)\r
-{\r
-       psx932x_t pDevice = 0;\r
-       psx932x_platform_data_t pdata = 0;\r
-       int i = 0;\r
-       /* configure device */\r
-       dev_info(this->pdev, "Going to Setup I2C Registers\n");\r
-       if (this && (pDevice = this->pDevice) && (pdata = pDevice->hw))\r
-       {\r
-               /*******************************************************************************/\r
-               // try to initialize from device tree!\r
-               /*******************************************************************************/\r
-               if (this->reg_in_dts == true) {\r
-                       while ( i < pdata->i2c_reg_num) {\r
-                               /* Write all registers/values contained in i2c_reg */\r
-                               dev_info(this->pdev, "Going to Write Reg from dts: 0x%x Value: 0x%x\n",\r
-                               pdata->pi2c_reg[i].reg,pdata->pi2c_reg[i].val);\r
-                               write_register(this, pdata->pi2c_reg[i].reg,pdata->pi2c_reg[i].val);\r
-                               i++;\r
-                       }\r
-               } else { // use static ones!!\r
-                       while ( i < ARRAY_SIZE(sx932x_i2c_reg_setup)) {\r
-                               /* Write all registers/values contained in i2c_reg */\r
-                               dev_info(this->pdev, "Going to Write Reg: 0x%x Value: 0x%x\n",\r
-                               sx932x_i2c_reg_setup[i].reg,sx932x_i2c_reg_setup[i].val);\r
-                               write_register(this, sx932x_i2c_reg_setup[i].reg,sx932x_i2c_reg_setup[i].val);\r
-                               i++;\r
-                       }\r
-               }\r
-       /*******************************************************************************/\r
-       } else {\r
-               dev_err(this->pdev, "ERROR! platform data 0x%p\n",pDevice->hw);\r
-       }\r
-\r
-}\r
-\r
-\r
-/*! \fn static int initialize(psx93XX_t this)\r
- * \brief Performs all initialization needed to configure the device\r
- * \param this Pointer to main parent struct\r
- * \return Last used command's return value (negative if error)\r
- */\r
-static int initialize(psx93XX_t this)\r
-{\r
-       int ret;\r
-       if (this) {\r
-               pr_info("SX9320 income initialize\n");\r
-               /* prepare reset by disabling any irq handling */\r
-               this->irq_disabled = 1;\r
-               disable_irq(this->irq);\r
-               /* perform a reset */\r
-               write_register(this,SX932x_SOFTRESET_REG,SX932x_SOFTRESET);\r
-               /* wait until the reset has finished by monitoring NIRQ */\r
-               dev_info(this->pdev, "Sent Software Reset. Waiting until device is back from reset to continue.\n");\r
-               /* just sleep for awhile instead of using a loop with reading irq status */\r
-               msleep(100);\r
-\r
-               ret = sx932x_global_variable_init(this);\r
-\r
-               sx932x_reg_init(this);\r
-               msleep(100); /* make sure everything is running */\r
-               manual_offset_calibration(this);\r
-\r
-               /* re-enable interrupt handling */\r
-               enable_irq(this->irq);\r
-\r
-               /* make sure no interrupts are pending since enabling irq will only\r
-               * work on next falling edge */\r
-               read_regStat(this);\r
-               return 0;\r
-       }\r
-       return -ENOMEM;\r
-}\r
-\r
-/*!\r
- * \brief Handle what to do when a touch occurs\r
- * \param this Pointer to main parent struct\r
- */\r
-static void touchProcess(psx93XX_t this)\r
-{\r
-       int counter = 0;\r
-       u8 i = 0;\r
-       int numberOfButtons = 0;\r
-       psx932x_t pDevice = NULL;\r
-       struct _buttonInfo *buttons = NULL;\r
-       struct input_dev *input = NULL;\r
-\r
-       struct _buttonInfo *pCurrentButton  = NULL;\r
-\r
-       if (this && (pDevice = this->pDevice))\r
-       {\r
-               //dev_info(this->pdev, "Inside touchProcess()\n");\r
-               read_register(this, SX932x_STAT0_REG, &i);\r
-\r
-               buttons = pDevice->pbuttonInformation->buttons;\r
-               input = pDevice->pbuttonInformation->input;\r
-               numberOfButtons = pDevice->pbuttonInformation->buttonSize;\r
-\r
-               if (unlikely( (buttons==NULL) || (input==NULL) )) {\r
-                       dev_err(this->pdev, "ERROR!! buttons or input NULL!!!\n");\r
-                       return;\r
-               }\r
-\r
-               for (counter = 0; counter < numberOfButtons; counter++) {\r
-                       pCurrentButton = &buttons[counter];\r
-                       if (pCurrentButton==NULL) {\r
-                               dev_err(this->pdev,"ERROR!! current button at index: %d NULL!!!\n", counter);\r
-                               return; // ERRORR!!!!\r
-                       }\r
-                       switch (pCurrentButton->state) {\r
-                               case IDLE: /* Button is not being touched! */\r
-                                       if (((i & pCurrentButton->mask) == pCurrentButton->mask)) {\r
-                                               /* User pressed button */\r
-                                               dev_info(this->pdev, "cap button %d touched\n", counter);\r
-                                               input_report_key(input, pCurrentButton->keycode, 1);\r
-                                               pCurrentButton->state = ACTIVE;\r
-                                       } else {\r
-                                               dev_info(this->pdev, "Button %d already released.\n",counter);\r
-                                       }\r
-                                       break;\r
-                               case ACTIVE: /* Button is being touched! */ \r
-                                       if (((i & pCurrentButton->mask) != pCurrentButton->mask)) {\r
-                                               /* User released button */\r
-                                               dev_info(this->pdev, "cap button %d released\n",counter);\r
-                                               input_report_key(input, pCurrentButton->keycode, 0);\r
-                                               pCurrentButton->state = IDLE;\r
-                                       } else {\r
-                                               dev_info(this->pdev, "Button %d still touched.\n",counter);\r
-                                       }\r
-                                       break;\r
-                               default: /* Shouldn't be here, device only allowed ACTIVE or IDLE */\r
-                                       break;\r
-                       };\r
-               }\r
-               input_sync(input);\r
-\r
-   //dev_info(this->pdev, "Leaving touchProcess()\n");\r
-  }\r
-}\r
-\r
-static int sx932x_parse_dt(struct sx932x_platform_data *pdata, struct device *dev)\r
-{\r
-       struct device_node *dNode = dev->of_node;\r
-       enum of_gpio_flags flags;\r
-       if (dNode == NULL)\r
-               return -ENODEV;\r
-\r
-       pdata->irq_gpio= of_get_named_gpio_flags(dNode,\r
-                                                                                       "Semtech,nirq-gpio", 0, &flags);\r
-       irq_gpio_num = pdata->irq_gpio;\r
-       if (pdata->irq_gpio < 0) {\r
-               pr_err("[SENSOR]: %s - get irq_gpio error\n", __func__);\r
-               return -ENODEV;\r
-       }\r
-\r
-       /***********************************************************************/\r
-       // load in registers from device tree\r
-       of_property_read_u32(dNode,"Semtech,reg-num",&pdata->i2c_reg_num);\r
-       // layout is register, value, register, value....\r
-       // if an extra item is after just ignore it. reading the array in will cause it to fail anyway\r
-       pr_info("[SX9320]:%s -  size of elements %d \n", __func__,pdata->i2c_reg_num);\r
-       if (pdata->i2c_reg_num > 0) {\r
-                // initialize platform reg data array\r
-                pdata->pi2c_reg = devm_kzalloc(dev,sizeof(struct smtc_reg_data)*pdata->i2c_reg_num, GFP_KERNEL);\r
-                if (unlikely(pdata->pi2c_reg == NULL)) {\r
-                       return -ENOMEM;\r
-               }\r
-\r
-        // initialize the array\r
-               if (of_property_read_u8_array(dNode,"Semtech,reg-init",(u8*)&(pdata->pi2c_reg[0]),sizeof(struct smtc_reg_data)*pdata->i2c_reg_num))\r
-               return -ENOMEM;\r
-       }\r
-       /***********************************************************************/\r
-       pr_info("[SX9320]: %s -[%d] parse_dt complete\n", __func__,pdata->irq_gpio);\r
-       return 0;\r
-}\r
-       struct pinctrl *pinctrl_int;\r
-/* get the NIRQ state (1->NIRQ-low, 0->NIRQ-high) */\r
-static int sx932x_init_platform_hw(struct i2c_client *client)\r
-{\r
-       psx93XX_t this = i2c_get_clientdata(client);\r
-       struct sx932x *pDevice = NULL;\r
-       struct sx932x_platform_data *pdata = NULL;\r
-\r
-       int rc;\r
-\r
-       pr_info("[SX9320] : %s init_platform_hw start!",__func__);\r
-\r
-       if (this && (pDevice = this->pDevice) && (pdata = pDevice->hw)) {\r
-               if (gpio_is_valid(pdata->irq_gpio)) {\r
-                       rc = gpio_request(pdata->irq_gpio, "sx9320_irq_gpio");\r
-                       if (rc < 0) {\r
-                               dev_err(this->pdev, "SX9320 Request gpio. Fail![%d]\n", rc);\r
-                               return rc;\r
-                       }\r
-                       rc = gpio_direction_input(pdata->irq_gpio);\r
-                       if (rc < 0) {\r
-                               dev_err(this->pdev, "SX9320 Set gpio direction. Fail![%d]\n", rc);\r
-                               return rc;\r
-                       }\r
-                       pinctrl_int = devm_pinctrl_get_select(this->pdev, "default");\r
-\r
-                       this->irq = client->irq = gpio_to_irq(pdata->irq_gpio);\r
-               }\r
-               else {\r
-                       dev_err(this->pdev, "SX9320 Invalid irq gpio num.(init)\n");\r
-               }\r
-       }\r
-       else {\r
-               pr_err("[SX9320] : %s - Do not init platform HW", __func__);\r
-       }\r
-\r
-       pr_err("[SX9320]: %s - sx9320_irq_debug\n",__func__);\r
-       return rc;\r
-}\r
-\r
-static void sx932x_exit_platform_hw(struct i2c_client *client)\r
-{\r
-       psx93XX_t this = i2c_get_clientdata(client);\r
-       struct sx932x *pDevice = NULL;\r
-       struct sx932x_platform_data *pdata = NULL;\r
-       printk("%s:test\n",__func__);\r
-       if (this && (pDevice = this->pDevice) && (pdata = pDevice->hw)) {\r
-               if (gpio_is_valid(pdata->irq_gpio)) {\r
-                       gpio_free(pdata->irq_gpio);\r
-               }\r
-               else {\r
-                       dev_err(this->pdev, "Invalid irq gpio num.(exit)\n");\r
-               }\r
-       }\r
-       return;\r
-}\r
-\r
-static int sx932x_get_nirq_state(void)\r
-{\r
-       return  !gpio_get_value(irq_gpio_num);\r
-}\r
-\r
-/*! \fn static int sx932x_probe(struct i2c_client *client, const struct i2c_device_id *id)\r
- * \brief Probe function\r
- * \param client pointer to i2c_client\r
- * \param id pointer to i2c_device_id\r
- * \return Whether probe was successful\r
- */\r
-static int sx932x_probe(struct i2c_client *client, const struct i2c_device_id *id)\r
-{\r
-       int i = 0;\r
-       int err = 0;\r
-       int ret = 0;\r
-       psx93XX_t this = 0;\r
-       psx932x_t pDevice = 0;\r
-       psx932x_platform_data_t pplatData = 0;\r
-       struct totalButtonInformation *pButtonInformationData = NULL;\r
-       struct input_dev *input = NULL;\r
-       struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent);\r
-\r
-       dev_info(&client->dev, "sx932x_probe()\n");\r
-\r
-       if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_READ_WORD_DATA)) {\r
-               dev_err(&client->dev, "Check i2c functionality.Fail!\n");\r
-               err = -EIO;\r
-               return err;\r
-       }\r
-\r
-       this = devm_kzalloc(&client->dev,sizeof(sx93XX_t), GFP_KERNEL); /* create memory for main struct */\r
-       dev_info(&client->dev, "\t Initialized Main Memory: 0x%p\n",this);\r
-\r
-       pButtonInformationData = devm_kzalloc(&client->dev , sizeof(struct totalButtonInformation), GFP_KERNEL);\r
-       if (!pButtonInformationData) {\r
-               dev_err(&client->dev, "Failed to allocate memory(totalButtonInformation)\n");\r
-               err = -ENOMEM;\r
-               return err;\r
-       }\r
-\r
-       pButtonInformationData->buttonSize = ARRAY_SIZE(psmtcButtons);\r
-       pButtonInformationData->buttons =  psmtcButtons;\r
-       pplatData = devm_kzalloc(&client->dev,sizeof(struct sx932x_platform_data), GFP_KERNEL);\r
-       if (!pplatData) {\r
-               dev_err(&client->dev, "platform data is required!\n");\r
-               return -EINVAL;\r
-       }\r
-       pplatData->cap_vdd = regulator_get(&client->dev, "cap_vdd");\r
-       if (IS_ERR(pplatData->cap_vdd)) {\r
-               if (PTR_ERR(pplatData->cap_vdd) == -EPROBE_DEFER) {\r
-                       ret = PTR_ERR(pplatData->cap_vdd);\r
-                       //goto err_vdd_defer;\r
-               }\r
-               dev_err(&client->dev,"%s: Failed to get regulator\n",\r
-                               __func__);\r
-       } else {\r
-               int error = regulator_enable(pplatData->cap_vdd);\r
-\r
-               if (error) {\r
-                       regulator_put(pplatData->cap_vdd);\r
-                       dev_err(&client->dev,"%s: Error %d enable regulator\n",\r
-                                       __func__, error);\r
-                       return error;\r
-               }\r
-               pplatData->cap_vdd_en = true;\r
-               dev_info(&client->dev,"cap_vdd regulator is %s\n",\r
-                       regulator_is_enabled(pplatData->cap_vdd) ?\r
-                       "on" : "off");\r
-       }\r
-       pplatData->get_is_nirq_low = sx932x_get_nirq_state;\r
-       pplatData->pbuttonInformation = pButtonInformationData;\r
-\r
-       client->dev.platform_data = pplatData;\r
-       err = sx932x_parse_dt(pplatData, &client->dev);\r
-       if (err) {\r
-               dev_err(&client->dev, "could not setup pin\n");\r
-               return ENODEV;\r
-       }\r
-\r
-       pplatData->init_platform_hw = sx932x_init_platform_hw;\r
-       dev_err(&client->dev, "SX9320 init_platform_hw done!\n");\r
-\r
-       if (this){\r
-               dev_info(&client->dev, "SX9320 initialize start!!");\r
-               /* In case we need to reinitialize data\r
-               * (e.q. if suspend reset device) */\r
-               this->init = initialize;\r
-               /* shortcut to read status of interrupt */\r
-               this->refreshStatus = read_regStat;\r
-               /* pointer to function from platform data to get pendown\r
-               * (1->NIRQ=0, 0->NIRQ=1) */\r
-               this->get_nirq_low = pplatData->get_is_nirq_low;\r
-               /* save irq in case we need to reference it */\r
-               this->irq = client->irq;\r
-               /* do we need to create an irq timer after interrupt ? */\r
-               this->useIrqTimer = 0;\r
-\r
-               /* Setup function to call on corresponding reg irq source bit */\r
-               if (MAX_NUM_STATUS_BITS>= 8)\r
-               {\r
-                       this->statusFunc[0] = 0; /* TXEN_STAT */\r
-                       this->statusFunc[1] = 0; /* UNUSED */\r
-                       this->statusFunc[2] = 0; /* UNUSED */\r
-                       this->statusFunc[3] = read_rawData; /* CONV_STAT */\r
-                       this->statusFunc[4] = 0; /* COMP_STAT */\r
-                       this->statusFunc[5] = touchProcess; /* RELEASE_STAT */\r
-                       this->statusFunc[6] = touchProcess; /* TOUCH_STAT  */\r
-                       this->statusFunc[7] = 0; /* RESET_STAT */\r
-               }\r
-\r
-               /* setup i2c communication */\r
-               this->bus = client;\r
-               i2c_set_clientdata(client, this);\r
-\r
-               /* record device struct */\r
-               this->pdev = &client->dev;\r
-\r
-               /* create memory for device specific struct */\r
-               this->pDevice = pDevice = devm_kzalloc(&client->dev,sizeof(sx932x_t), GFP_KERNEL);\r
-               dev_info(&client->dev, "\t Initialized Device Specific Memory: 0x%p\n",pDevice);\r
-\r
-               if (pDevice){\r
-                       /* for accessing items in user data (e.g. calibrate) */\r
-                       err = sysfs_create_group(&client->dev.kobj, &sx932x_attr_group);\r
-                       //sysfs_create_group(client, &sx932x_attr_group);\r
-\r
-                       /* Add Pointer to main platform data struct */\r
-                       pDevice->hw = pplatData;\r
-\r
-                       /* Check if we hava a platform initialization function to call*/\r
-                       if (pplatData->init_platform_hw)\r
-                       pplatData->init_platform_hw(client);\r
-\r
-                       /* Initialize the button information initialized with keycodes */\r
-                       pDevice->pbuttonInformation = pplatData->pbuttonInformation;\r
-                       /* Create the input device */\r
-                       input = input_allocate_device();\r
-                       if (!input) {\r
-                               return -ENOMEM;\r
-                       }\r
-                       /* Set all the keycodes */\r
-                       __set_bit(EV_KEY, input->evbit);\r
-                       #if 1\r
-                       for (i = 0; i < pButtonInformationData->buttonSize; i++) {\r
-                               __set_bit(pButtonInformationData->buttons[i].keycode,input->keybit);\r
-                               pButtonInformationData->buttons[i].state = IDLE;\r
-                       }\r
-                       #endif\r
-                       /* save the input pointer and finish initialization */\r
-                       pButtonInformationData->input = input;\r
-                       input->name = "SX9320 Cap Touch";\r
-                       input->id.bustype = BUS_I2C;\r
-                       if(input_register_device(input)){\r
-                               return -ENOMEM;\r
-                       }\r
-               }\r
-\r
-               sx93XX_IRQ_init(this);\r
-               /* call init function pointer (this should initialize all registers */\r
-               if (this->init){\r
-                       this->init(this);\r
-               }else{\r
-                       dev_err(this->pdev,"No init function!!!!\n");\r
-                       return -ENOMEM;\r
-               }\r
-       }else{\r
-               return -1;\r
-       }\r
-\r
-       sx932x_Hardware_Check(this);\r
-       pplatData->exit_platform_hw = sx932x_exit_platform_hw;\r
-       dev_info(&client->dev, "sx932x_probe() Done\n");\r
-\r
-       return 0;\r
-}\r
-\r
-/*! \fn static int sx932x_remove(struct i2c_client *client)\r
- * \brief Called when device is to be removed\r
- * \param client Pointer to i2c_client struct\r
- * \return Value from sx93XX_remove()\r
- */\r
-//static int __devexit sx932x_remove(struct i2c_client *client)\r
-static int sx932x_remove(struct i2c_client *client)\r
-{\r
-       psx932x_platform_data_t pplatData =0;\r
-       psx932x_t pDevice = 0;\r
-       psx93XX_t this = i2c_get_clientdata(client);\r
-       if (this && (pDevice = this->pDevice))\r
-       {\r
-               input_unregister_device(pDevice->pbuttonInformation->input);\r
-\r
-               sysfs_remove_group(&client->dev.kobj, &sx932x_attr_group);\r
-               pplatData = client->dev.platform_data;\r
-               if (pplatData && pplatData->exit_platform_hw)\r
-                       pplatData->exit_platform_hw(client);\r
-               kfree(this->pDevice);\r
-       }\r
-       return sx93XX_remove(this);\r
-}\r
-#if 1//def CONFIG_PM\r
-/*====================================================*/\r
-/***** Kernel Suspend *****/\r
-static int sx932x_suspend(struct device *dev)\r
-{\r
-       psx93XX_t this = dev_get_drvdata(dev);\r
-       sx93XX_suspend(this);\r
-       return 0;\r
-}\r
-/***** Kernel Resume *****/\r
-static int sx932x_resume(struct device *dev)\r
-{\r
-       psx93XX_t this = dev_get_drvdata(dev);\r
-       sx93XX_resume(this);\r
-       return 0;\r
-}\r
-/*====================================================*/\r
-#else\r
-#define sx932x_suspend         NULL\r
-#define sx932x_resume          NULL\r
-#endif /* CONFIG_PM */\r
-\r
-static struct i2c_device_id sx932x_idtable[] = {\r
-       { DRIVER_NAME, 0 },\r
-       { }\r
-};\r
-MODULE_DEVICE_TABLE(i2c, sx932x_idtable);\r
-#ifdef CONFIG_OF\r
-static struct of_device_id sx932x_match_table[] = {\r
-       { .compatible = "Semtech,sx932x",},\r
-       { },\r
-};\r
-#else\r
-#define sx932x_match_table NULL\r
-#endif\r
-static const struct dev_pm_ops sx932x_pm_ops = {\r
-       .suspend = sx932x_suspend,\r
-       .resume = sx932x_resume,\r
-};\r
-static struct i2c_driver sx932x_driver = {\r
-       .driver = {\r
-               .owner                  = THIS_MODULE,\r
-               .name                   = DRIVER_NAME,\r
-               .of_match_table = sx932x_match_table,\r
-               .pm                             = &sx932x_pm_ops,\r
-       },\r
-       .id_table               = sx932x_idtable,\r
-       .probe                  = sx932x_probe,\r
-       .remove                 = sx932x_remove,\r
-};\r
-static int __init sx932x_I2C_init(void)\r
-{\r
-       return i2c_add_driver(&sx932x_driver);\r
-}\r
-static void __exit sx932x_I2C_exit(void)\r
-{\r
-       i2c_del_driver(&sx932x_driver);\r
-}\r
-\r
-module_init(sx932x_I2C_init);\r
-module_exit(sx932x_I2C_exit);\r
-\r
-MODULE_AUTHOR("Semtech Corp. (http://www.semtech.com/)");\r
-MODULE_DESCRIPTION("SX9320 Capacitive Touch Controller Driver");\r
-MODULE_LICENSE("GPL");\r
-MODULE_VERSION("0.1");\r
-\r
-static void sx93XX_schedule_work(psx93XX_t this, unsigned long delay)\r
-{\r
-       unsigned long flags;\r
-       if (this) {\r
-               dev_info(this->pdev, "sx93XX_schedule_work()\n");\r
-               spin_lock_irqsave(&this->lock,flags);\r
-               /* Stop any pending penup queues */\r
-               cancel_delayed_work(&this->dworker);\r
-               //after waiting for a delay, this put the job in the kernel-global workqueue. so no need to create new thread in work queue.\r
-               schedule_delayed_work(&this->dworker,delay);\r
-               spin_unlock_irqrestore(&this->lock,flags);\r
-       }\r
-       else\r
-               printk(KERN_ERR "sx93XX_schedule_work, NULL psx93XX_t\n");\r
-} \r
-\r
-static irqreturn_t sx93XX_irq(int irq, void *pvoid)\r
-{\r
-       psx93XX_t this = 0;\r
-       if (pvoid) {\r
-               this = (psx93XX_t)pvoid;\r
-               if ((!this->get_nirq_low) || this->get_nirq_low()) {\r
-               sx93XX_schedule_work(this,0);\r
-               }\r
-               else{\r
-                       dev_err(this->pdev, "sx93XX_irq - nirq read high\n");\r
-               }\r
-       }\r
-       else{\r
-               printk(KERN_ERR "sx93XX_irq, NULL pvoid\n");\r
-       }\r
-       return IRQ_HANDLED;\r
-}\r
-\r
-static void sx93XX_worker_func(struct work_struct *work)\r
-{\r
-       psx93XX_t this = 0;\r
-       int status = 0;\r
-       int counter = 0;\r
-       u8 nirqLow = 0;\r
-       if (work) {\r
-               this = container_of(work,sx93XX_t,dworker.work);\r
-\r
-               if (!this) {\r
-                       printk(KERN_ERR "sx93XX_worker_func, NULL sx93XX_t\n");\r
-                       return;\r
-               }\r
-               if (unlikely(this->useIrqTimer)) {\r
-                       if ((!this->get_nirq_low) || this->get_nirq_low()) {\r
-                               nirqLow = 1;\r
-                       }\r
-               }\r
-               /* since we are not in an interrupt don't need to disable irq. */\r
-               status = this->refreshStatus(this);\r
-               counter = -1;\r
-               dev_dbg(this->pdev, "Worker - Refresh Status %d\n",status);\r
-\r
-               while((++counter) < MAX_NUM_STATUS_BITS) { /* counter start from MSB */\r
-                       if (((status>>counter) & 0x01) && (this->statusFunc[counter])) {\r
-                               dev_info(this->pdev, "SX9320 Function Pointer Found. Calling\n");\r
-                               this->statusFunc[counter](this);\r
-                       }\r
-               }\r
-               if (unlikely(this->useIrqTimer && nirqLow))\r
-               {       /* Early models and if RATE=0 for newer models require a penup timer */\r
-                       /* Queue up the function again for checking on penup */\r
-                       sx93XX_schedule_work(this,msecs_to_jiffies(this->irqTimeout));\r
-               }\r
-       } else {\r
-               printk(KERN_ERR "sx93XX_worker_func, NULL work_struct\n");\r
-       }\r
-}\r
-\r
-int sx93XX_remove(psx93XX_t this)\r
-{\r
-       if (this) {\r
-               cancel_delayed_work_sync(&this->dworker); /* Cancel the Worker Func */\r
-               /*destroy_workqueue(this->workq); */\r
-               free_irq(this->irq, this);\r
-               kfree(this);\r
-               return 0;\r
-       }\r
-       return -ENOMEM;\r
-}\r
-void sx93XX_suspend(psx93XX_t this)\r
-{\r
-       if (this)\r
-               disable_irq(this->irq);\r
-\r
-       //write_register(this,SX932x_CTRL1_REG,0x20);//make sx932x in Sleep mode\r
-}\r
-void sx93XX_resume(psx93XX_t this)\r
-{\r
-       if (this) {\r
-               sx93XX_schedule_work(this,0);\r
-               if (this->init)\r
-                       this->init(this);\r
-       enable_irq(this->irq);\r
-       }\r
-}\r
-\r
-int sx93XX_IRQ_init(psx93XX_t this)\r
-{\r
-       int err = 0;\r
-       if (this && this->pDevice)\r
-       {\r
-               /* initialize spin lock */\r
-               spin_lock_init(&this->lock);\r
-               /* initialize worker function */\r
-               INIT_DELAYED_WORK(&this->dworker, sx93XX_worker_func);\r
-               /* initailize interrupt reporting */\r
-               this->irq_disabled = 0;\r
-               err = request_irq(this->irq, sx93XX_irq, IRQF_TRIGGER_FALLING,\r
-                                                       this->pdev->driver->name, this);\r
-               if (err) {\r
-                       dev_err(this->pdev, "irq %d busy?\n", this->irq);\r
-                       return err;\r
-               }\r
-               printk("%s:test registered with irq \n",__func__);\r
-               dev_info(this->pdev, "registered with irq (%d)\n", this->irq);\r
-       }\r
-       return -ENOMEM;\r
-}\r
diff --git a/drivers/input/misc/sx932x.h b/drivers/input/misc/sx932x.h
deleted file mode 100755 (executable)
index 759d09b..0000000
+++ /dev/null
@@ -1,461 +0,0 @@
-/*\r
-* This program is free software; you can redistribute it and/or\r
-* modify it under the terms of the GNU General Public License\r
-* version 2 as published by the Free Software Foundation.\r
-*/\r
-#ifndef SX932x_H\r
-#define SX932x_H\r
-\r
-#include <linux/device.h>\r
-#include <linux/slab.h>\r
-#include <linux/interrupt.h>\r
-\r
-#if 0\r
-#include <linux/wakelock.h>\r
-#include <linux/earlysuspend.h>\r
-#include <linux/suspend.h>\r
-#endif\r
-\r
-/*\r
-*  I2C Registers\r
-*/\r
-//-Interrupt and status\r
-#define SX932x_IRQSTAT_REG             0x00\r
-#define SX932x_STAT0_REG               0x01\r
-#define SX932x_STAT1_REG               0x02\r
-#define SX932x_STAT2_REG               0x03\r
-#define SX932x_STAT3_REG               0x04\r
-#define SX932x_IRQ_ENABLE_REG  0x05\r
-#define SX932x_IRQCFG0_REG             0x06\r
-#define SX932x_IRQCFG1_REG             0x07\r
-#define SX932x_IRQCFG2_REG             0x08\r
-//-General control\r
-#define SX932x_CTRL0_REG               0x10\r
-#define SX932x_CTRL1_REG               0x11\r
-#define SX932x_I2CADDR_REG             0x14\r
-#define SX932x_CLKSPRD                 0x15\r
-//-AFE Control\r
-#define SX932x_AFE_CTRL0_REG   0x20\r
-#define SX932x_AFE_CTRL1_REG   0x21\r
-#define SX932x_AFE_CTRL2_REG   0x22\r
-#define SX932x_AFE_CTRL3_REG   0x23\r
-#define SX932x_AFE_CTRL4_REG   0x24\r
-#define SX932x_AFE_CTRL5_REG   0x25\r
-#define SX932x_AFE_CTRL6_REG   0x26\r
-#define SX932x_AFE_CTRL7_REG   0x27\r
-#define SX932x_AFE_PH0_REG             0x28\r
-#define SX932x_AFE_PH1_REG             0x29\r
-#define SX932x_AFE_PH2_REG             0x2A\r
-#define SX932x_AFE_PH3_REG             0x2B\r
-#define SX932x_AFE_CTRL8               0x2C\r
-#define SX932x_AFE_CTRL9               0x2D\r
-//-Main Digital Processing (Prox) control\r
-#define SX932x_PROX_CTRL0_REG  0x30\r
-#define SX932x_PROX_CTRL1_REG  0x31\r
-#define SX932x_PROX_CTRL2_REG  0x32\r
-#define SX932x_PROX_CTRL3_REG  0x33\r
-#define SX932x_PROX_CTRL4_REG  0x34\r
-#define SX932x_PROX_CTRL5_REG  0x35\r
-#define SX932x_PROX_CTRL6_REG  0x36\r
-#define SX932x_PROX_CTRL7_REG  0x37\r
-//-Advanced Digital Processing control\r
-#define SX932x_ADV_CTRL0_REG   0x40\r
-#define SX932x_ADV_CTRL1_REG   0x41\r
-#define SX932x_ADV_CTRL2_REG   0x42\r
-#define SX932x_ADV_CTRL3_REG   0x43\r
-#define SX932x_ADV_CTRL4_REG   0x44\r
-#define SX932x_ADV_CTRL5_REG   0x45\r
-#define SX932x_ADV_CTRL6_REG   0x46\r
-#define SX932x_ADV_CTRL7_REG   0x47\r
-#define SX932x_ADV_CTRL8_REG   0x48\r
-#define SX932x_ADV_CTRL9_REG   0x49\r
-#define SX932x_ADV_CTRL10_REG  0x4A\r
-#define SX932x_ADV_CTRL11_REG  0x4B\r
-#define SX932x_ADV_CTRL12_REG  0x4C\r
-#define SX932x_ADV_CTRL13_REG  0x4D\r
-#define SX932x_ADV_CTRL14_REG  0x4E\r
-#define SX932x_ADV_CTRL15_REG  0x4F\r
-#define SX932x_ADV_CTRL16_REG  0x50\r
-#define SX932x_ADV_CTRL17_REG  0x51\r
-#define SX932x_ADV_CTRL18_REG  0x52\r
-#define SX932x_ADV_CTRL19_REG  0x53\r
-#define SX932x_ADV_CTRL20_REG  0x54\r
-/*      Sensor Readback */\r
-#define SX932x_CPSRD                   0x60\r
-#define SX932x_USEMSB                  0x61\r
-#define SX932x_USELSB                  0x62\r
-#define SX932x_AVGMSB                  0x63\r
-#define SX932x_AVGLSB                  0x64\r
-#define SX932x_DIFFMSB                 0x65\r
-#define SX932x_DIFFLSB                 0x66\r
-#define SX932x_OFFSETMSB               0x67\r
-#define SX932x_OFFSETLSB               0x68\r
-#define SX932x_SARMSB                  0x69\r
-#define SX932x_SARLSB                  0x6A\r
-\r
-#define SX932x_SOFTRESET_REG   0x9F\r
-#define SX932x_WHOAMI_REG              0xFA\r
-#define SX932x_REV_REG                 0xFB\r
-\r
-/*      IrqStat 0:Inactive 1:Active     */\r
-#define SX932x_IRQSTAT_RESET_FLAG              0x80\r
-#define SX932x_IRQSTAT_TOUCH_FLAG              0x40\r
-#define SX932x_IRQSTAT_RELEASE_FLAG            0x20\r
-#define SX932x_IRQSTAT_COMPDONE_FLAG   0x10\r
-#define SX932x_IRQSTAT_CONV_FLAG               0x08\r
-#define SX932x_IRQSTAT_PROG2_FLAG              0x04\r
-#define SX932x_IRQSTAT_PROG1_FLAG              0x02\r
-#define SX932x_IRQSTAT_PROG0_FLAG              0x01\r
-\r
-\r
-/* RegStat0  */\r
-#define SX932x_PROXSTAT_PH3_FLAG               0x08\r
-#define SX932x_PROXSTAT_PH2_FLAG               0x04\r
-#define SX932x_PROXSTAT_PH1_FLAG               0x02\r
-#define SX932x_PROXSTAT_PH0_FLAG               0x01\r
-\r
-/*      SoftReset */\r
-#define SX932x_SOFTRESET                               0xDE\r
-#define SX932x_WHOAMI_VALUE                            0x22  //just for sx9325\r
-#define SX932x_REV_VALUE                               0x22 //just for sx9325\r
-\r
-#define LGE_SENSOR\r
-\r
-/**************************************\r
-*   define platform data\r
-*\r
-**************************************/\r
-struct smtc_reg_data {\r
-       unsigned char reg;\r
-       unsigned char val;\r
-};\r
-typedef struct smtc_reg_data smtc_reg_data_t;\r
-typedef struct smtc_reg_data *psmtc_reg_data_t;\r
-\r
-\r
-struct _buttonInfo {\r
-       /*! The Key to send to the input */\r
-       int keycode;\r
-       /*! Mask to look for on Touch Status */\r
-       int mask;\r
-       /*! Current state of button. */\r
-       int state;\r
-};\r
-\r
-struct totalButtonInformation {\r
-       struct _buttonInfo *buttons;\r
-       int buttonSize;\r
-       struct input_dev *input;\r
-};\r
-\r
-typedef struct totalButtonInformation buttonInformation_t;\r
-typedef struct totalButtonInformation *pbuttonInformation_t;\r
-\r
-/* Define Registers that need to be initialized to values different than\r
-* default\r
-*/\r
-static struct smtc_reg_data sx932x_i2c_reg_setup[] = {\r
-//Interrupt and config\r
-       {\r
-               .reg = SX932x_IRQ_ENABLE_REG,   //0x05\r
-               .val = 0x70,                                    // Enavle Close and Far -> enable compensation interrupt\r
-       },\r
-       {\r
-               .reg = SX932x_IRQCFG0_REG,              //0x06\r
-               .val = 0x00,                                    //\r
-       },\r
-       {\r
-               .reg = SX932x_IRQCFG1_REG,              //0x07  \r
-               .val = 0x00,\r
-       },\r
-       {\r
-               .reg = SX932x_IRQCFG2_REG,              //0x08\r
-               .val = 0x00,                                    //Activ Low\r
-       },\r
-       //--------General control\r
-       {\r
-               .reg = SX932x_CTRL0_REG,    //0x10\r
-               .val = 0x16,       // Scanperiod : 100ms(10110)\r
-       },\r
-       {\r
-               .reg = SX932x_I2CADDR_REG,   //0x14\r
-               .val = 0x00,       //I2C Address : 0x28\r
-       },\r
-       {\r
-               .reg = SX932x_CLKSPRD,    //0x15\r
-               .val = 0x00,       //\r
-       },\r
-       //--------AFE Control\r
-       {\r
-               .reg = SX932x_AFE_CTRL0_REG,   //0x20\r
-               .val = 0x00,       // CSx pin during sleep mode : HZ\r
-       },\r
-       {\r
-               .reg = SX932x_AFE_CTRL1_REG,   //0x21\r
-               .val = 0x10,       //reserved\r
-       },\r
-       {\r
-               .reg = SX932x_AFE_CTRL2_REG,   //0x22\r
-               .val = 0x00,       //reserved\r
-       },\r
-       {\r
-               .reg = SX932x_AFE_CTRL3_REG,   //0x23\r
-               .val = 0x00,       //Analog Range(ph0/1) : Small\r
-       },\r
-       {\r
-               .reg = SX932x_AFE_CTRL4_REG,   //0x24\r
-               .val = 0x44,       //Sampling Freq(ph0/1) : 83.33khz(01000), Resolution(ph0/1) : 128(100)\r
-       },\r
-       {\r
-               .reg = SX932x_AFE_CTRL5_REG,   //0x25\r
-               .val = 0x00,       //reserved\r
-       },\r
-       {\r
-               .reg = SX932x_AFE_CTRL6_REG,   //0x26\r
-               .val = 0x01,       //big//Analog Range(ph2/3) : Small\r
-       },\r
-       {\r
-               .reg = SX932x_AFE_CTRL7_REG,   //0x27\r
-               .val = 0x44,       //Sampling Freq(ph2/3) : 83.33khz(01000), Resolution(ph2/3) : 128(100)\r
-       },\r
-       {\r
-               .reg = SX932x_AFE_PH0_REG,   //0x28\r
-               .val = 0x01,       // CS2:HZ CS1:Input CS0 :HZ\r
-       },\r
-       {\r
-               .reg = SX932x_AFE_PH1_REG,     //0x29\r
-               .val = 0x4,       // CS2:Input CS1:HZ Shield CS0 :HZ\r
-       },\r
-       {\r
-               .reg = SX932x_AFE_PH2_REG,   //0x2A\r
-               .val = 0x10,       //CS2:HZ CS1:HZ CS0 :HZ  \r
-       },\r
-       {\r
-               .reg = SX932x_AFE_PH3_REG,   //0x2B\r
-               .val = 0x00,       //CS2:HZ CS1:HZ CS0 :HZ\r
-       },\r
-       {\r
-               .reg = SX932x_AFE_CTRL8,    //0x2C\r
-               .val = 0x12,       // input register(kohm) 4(0010)\r
-       },\r
-       {\r
-               .reg = SX932x_AFE_CTRL9,    //0x2D\r
-               .val = 0x08,       // Analg gain : x1(1000)\r
-       },\r
-       //--------PROX control\r
-       {\r
-               .reg = SX932x_PROX_CTRL0_REG,  //0x30\r
-               .val = 0x09,       // Digital Gain(ph0/1) : off(001) Digital Filter(ph0/1) : 1-1/2(001)\r
-       },\r
-       {\r
-               .reg = SX932x_PROX_CTRL1_REG,  //0x31\r
-               .val = 0x09,       // Digital Gain(ph2/3) : off(001) Digital Filter(ph2/3) : 1-1/2(001)\r
-       },\r
-       {\r
-               .reg = SX932x_PROX_CTRL2_REG,  //0x32\r
-               .val = 0x08,       //AVGNEGTHRESH : 16384\r
-       },\r
-       {\r
-               .reg = SX932x_PROX_CTRL3_REG,  // 0x33 \r
-               .val = 0x20,       //AVGPOSTHRESH : 16384\r
-       },\r
-       {\r
-               .reg = SX932x_PROX_CTRL4_REG,  //0x34 \r
-               .val = 0x0C,       //AVGFREEZEDIS : on(0) ,AVGNEGFILT :1-1/2(001) ,AVGPOSFILT : 1-1/256(100)\r
-       },\r
-       {\r
-               .reg = SX932x_PROX_CTRL5_REG,  //0x35\r
-               .val = 0x00,       //FARCOND: PROXDIFF < (THRESH.HYST), HYST : None, CLOSEDEB : off ,FARDEB : off\r
-       },\r
-       {\r
-               .reg = SX932x_PROX_CTRL6_REG,  //0x36\r
-               .val = 0x1B,       // Prox Theshold(ph0/1) : 200\r
-       },\r
-       {\r
-               .reg = SX932x_PROX_CTRL7_REG,  //0x37\r
-               .val = 0x1B,       // Prox Theshold(ph2/3) : 200\r
-       },\r
-       //--------Advanced control (defult)\r
-       {\r
-               .reg = SX932x_ADV_CTRL0_REG,\r
-               .val = 0x00,\r
-       },\r
-       {\r
-               .reg = SX932x_ADV_CTRL1_REG,\r
-               .val = 0x00,\r
-       },\r
-       {\r
-               .reg = SX932x_ADV_CTRL2_REG,\r
-               .val = 0x00,\r
-       },\r
-       {\r
-               .reg = SX932x_ADV_CTRL3_REG,\r
-               .val = 0x00,\r
-       },\r
-       {\r
-               .reg = SX932x_ADV_CTRL4_REG,\r
-               .val = 0x00,\r
-       },\r
-       {\r
-               .reg = SX932x_ADV_CTRL5_REG,\r
-               .val = 0x05,\r
-       },\r
-       {\r
-               .reg = SX932x_ADV_CTRL6_REG,\r
-               .val = 0x00,\r
-       },\r
-       {\r
-               .reg = SX932x_ADV_CTRL7_REG,\r
-               .val = 0x00,\r
-       },\r
-       {\r
-               .reg = SX932x_ADV_CTRL8_REG,\r
-               .val = 0x00,\r
-       },\r
-       {\r
-               .reg = SX932x_ADV_CTRL9_REG,\r
-               .val = 0x80,\r
-       },\r
-       {\r
-               .reg = SX932x_ADV_CTRL10_REG,\r
-               .val = 0x00,\r
-       },\r
-       {\r
-               .reg = SX932x_ADV_CTRL11_REG,\r
-               .val = 0x00,\r
-       },\r
-       {\r
-               .reg = SX932x_ADV_CTRL12_REG,\r
-               .val = 0x00,\r
-       },\r
-       {\r
-               .reg = SX932x_ADV_CTRL13_REG,\r
-               .val = 0x00,\r
-       },\r
-       {\r
-               .reg = SX932x_ADV_CTRL14_REG,\r
-               .val = 0x80,\r
-       },\r
-       {\r
-               .reg = SX932x_ADV_CTRL15_REG,\r
-               .val = 0x0C,\r
-       },\r
-       {\r
-               .reg = SX932x_ADV_CTRL16_REG,\r
-               .val = 0x00,\r
-       },\r
-       {\r
-               .reg = SX932x_ADV_CTRL17_REG,\r
-               .val = 0x70,\r
-       },\r
-       {\r
-               .reg = SX932x_ADV_CTRL18_REG,\r
-               .val = 0x20,\r
-       },\r
-       {\r
-               .reg = SX932x_ADV_CTRL19_REG,\r
-               .val = 0xe1,\r
-       },\r
-       {\r
-               .reg = SX932x_ADV_CTRL20_REG,\r
-               .val = 0xF0,\r
-       },\r
-       //--------Sensor enable\r
-       {\r
-               .reg = SX932x_CTRL1_REG,    //0x11\r
-               .val = 0x27,       //enable PH2\r
-       },\r
-};\r
-\r
-static struct _buttonInfo psmtcButtons[] = {\r
-       {\r
-               .keycode = KEY_0,\r
-               .mask = SX932x_PROXSTAT_PH0_FLAG,\r
-       },\r
-       {\r
-               .keycode = KEY_1,\r
-               .mask = SX932x_PROXSTAT_PH1_FLAG,\r
-       },\r
-       {\r
-               .keycode = KEY_2,\r
-               .mask = SX932x_PROXSTAT_PH2_FLAG,\r
-       },\r
-       {\r
-               .keycode = KEY_3,\r
-               .mask = SX932x_PROXSTAT_PH3_FLAG,\r
-       },\r
-};\r
-\r
-struct sx932x_platform_data {\r
-       int i2c_reg_num;\r
-       struct smtc_reg_data *pi2c_reg;\r
-       int irq_gpio;\r
-       struct regulator *cap_vdd;\r
-       bool cap_vdd_en;\r
-       pbuttonInformation_t pbuttonInformation;\r
-\r
-       int (*get_is_nirq_low)(void);\r
-       u8 input_mainsensor;  // 0x01 ~ 0x02,//Startup function\r
-       u8 input_refsensor;   // 0x00 ~ 0x02,//Startup function\r
-       \r
-       int     (*init_platform_hw)(struct i2c_client *client);\r
-       void    (*exit_platform_hw)(struct i2c_client *client);\r
-};\r
-typedef struct sx932x_platform_data sx932x_platform_data_t;\r
-typedef struct sx932x_platform_data *psx932x_platform_data_t;\r
-\r
-/***************************************\r
-*  define data struct/interrupt\r
-*\r
-***************************************/\r
-\r
-#define MAX_NUM_STATUS_BITS (8)\r
-\r
-typedef struct sx93XX sx93XX_t, *psx93XX_t;\r
-struct sx93XX \r
-{\r
-       void * bus; /* either i2c_client or spi_client */\r
-\r
-       struct device *pdev; /* common device struction for linux */\r
-\r
-       void *pDevice; /* device specific struct pointer */\r
-\r
-       /* Function Pointers */\r
-       int (*init)(psx93XX_t this); /* (re)initialize device */\r
-\r
-       /* since we are trying to avoid knowing registers, create a pointer to a\r
-       * common read register which would be to read what the interrupt source\r
-       * is from \r
-       */\r
-       int (*refreshStatus)(psx93XX_t this); /* read register status */\r
-\r
-       int (*get_nirq_low)(void); /* get whether nirq is low (platform data) */\r
-\r
-       /* array of functions to call for corresponding status bit */\r
-       void (*statusFunc[MAX_NUM_STATUS_BITS])(psx93XX_t this); \r
-       \r
-       /* Global variable */\r
-       u8              failStatusCode; /*Fail status code*/\r
-       bool    reg_in_dts;\r
-\r
-       spinlock_t       lock; /* Spin Lock used for nirq worker function */\r
-       int irq; /* irq number used */\r
-\r
-       /* whether irq should be ignored.. cases if enable/disable irq is not used\r
-       * or does not work properly */\r
-       char irq_disabled;\r
-\r
-       u8 useIrqTimer; /* older models need irq timer for pen up cases */\r
-\r
-       int irqTimeout; /* msecs only set if useIrqTimer is true */\r
-\r
-       /* struct workqueue_struct *ts_workq;  */  /* if want to use non default */\r
-       struct delayed_work dworker; /* work struct for worker function */\r
-};\r
-\r
-void sx93XX_suspend(psx93XX_t this);\r
-void sx93XX_resume(psx93XX_t this);\r
-int sx93XX_IRQ_init(psx93XX_t this);\r
-int sx93XX_remove(psx93XX_t this);\r
-\r
-#endif\r
index c20e876efe12e765c1c72c194be4497ed15cfdc1..5666bee68d558d195780637c38aeff7c882de76e 100755 (executable)
@@ -51,6 +51,7 @@
 
 #define SENSOR_TYPE_DEVICE_PRIVATE_BASE                0x10000
 #define SENSOR_TYPE_CAP_PROX   (SENSOR_TYPE_DEVICE_PRIVATE_BASE + 2)
+#define SENSOR_TYPE_MOTO_CAPSENSE      (SENSOR_TYPE_DEVICE_PRIVATE_BASE + 16)
 
 enum LIS3DH_AXIS {
        AXIS_X = 0,