add new driver for all sensors
authorlw <lw@rock-chips.com>
Wed, 13 Jun 2012 06:50:24 +0000 (14:50 +0800)
committerlw <lw@rock-chips.com>
Wed, 13 Jun 2012 06:50:24 +0000 (14:50 +0800)
32 files changed:
arch/arm/plat-rk/include/plat/board.h
drivers/input/Kconfig
drivers/input/Makefile
drivers/input/sensors/Kconfig [new file with mode: 0755]
drivers/input/sensors/Makefile [new file with mode: 0755]
drivers/input/sensors/accel/Kconfig [new file with mode: 0755]
drivers/input/sensors/accel/Makefile [new file with mode: 0755]
drivers/input/sensors/accel/kxtik.c [new file with mode: 0755]
drivers/input/sensors/accel/mma8452.c [new file with mode: 0755]
drivers/input/sensors/compass/Kconfig [new file with mode: 0755]
drivers/input/sensors/compass/Makefile [new file with mode: 0755]
drivers/input/sensors/compass/ak8975.c [new file with mode: 0755]
drivers/input/sensors/gyro/Kconfig [new file with mode: 0755]
drivers/input/sensors/gyro/Makefile [new file with mode: 0755]
drivers/input/sensors/gyro/l3g4200d.c [new file with mode: 0755]
drivers/input/sensors/lsensor/Kconfig [new file with mode: 0755]
drivers/input/sensors/lsensor/Makefile [new file with mode: 0755]
drivers/input/sensors/lsensor/cm3217.c [new file with mode: 0755]
drivers/input/sensors/lsensor/ls_al3006.c [new file with mode: 0755]
drivers/input/sensors/lsensor/ls_stk3171.c [new file with mode: 0755]
drivers/input/sensors/psensor/Kconfig [new file with mode: 0755]
drivers/input/sensors/psensor/Makefile [new file with mode: 0755]
drivers/input/sensors/psensor/ps_al3006.c [new file with mode: 0755]
drivers/input/sensors/psensor/ps_stk3171.c [new file with mode: 0755]
drivers/input/sensors/sensor-dev.c [new file with mode: 0755]
drivers/input/sensors/sensor-i2c.c [new file with mode: 0755]
drivers/input/sensors/temperature/Kconfig [new file with mode: 0755]
drivers/input/sensors/temperature/Makefile [new file with mode: 0755]
include/linux/akm8975.h [changed mode: 0644->0755]
include/linux/kxtik.h [new file with mode: 0755]
include/linux/l3g4200d.h
include/linux/sensor-dev.h [new file with mode: 0755]

index 98fee642d8040f7e47122908ed90095996cecb3c..331f65ff395e2f78aedc48e242f0bef18ac7cbb1 100755 (executable)
@@ -90,12 +90,34 @@ struct gsensor_platform_data {
        void (*exit_platform_hw)(void);
 };
 
+
 struct akm8975_platform_data {
        short m_layout[4][3][3];
        char project_name[64];
        int gpio_DRDY;
 };
 
+struct sensor_platform_data {
+       int type;
+       int irq;
+       int power_pin;
+       int reset_pin;
+       int irq_enable;         //if irq_enable=1 then use irq else use polling  
+       int poll_delay_ms;      //polling
+       int x_min;              //filter
+       int y_min;
+       int z_min;
+       unsigned char address;
+       signed char orientation[9];
+       short m_layout[4][3][3];
+       char project_name[64];
+       int (*init_platform_hw)(void);
+       void (*exit_platform_hw)(void);
+       int (*power_on)(void);
+       int (*power_off)(void);
+};
+
+
 struct goodix_platform_data {
        int model ;
        int rest_pin;
index d52a16a23a4a76bdd273b872b5d9180dd7d08c36..972b67ffaffd0a3307db34b37e8e5aadd945b9c2 100755 (executable)
@@ -194,6 +194,7 @@ source "drivers/input/jogball/Kconfig"
 
 source "drivers/input/lightsensor/Kconfig"
 
+source "drivers/input/sensors/Kconfig"
 
 endif
 
index 7b058fb4b7f402dae2d730aff28fcc68f2940c7d..d9f2e938540e029b7a20a1ee64177c8c4ca3aa4b 100755 (executable)
@@ -28,5 +28,7 @@ obj-$(CONFIG_INPUT_JOGBALL)   += jogball/
 obj-$(CONFIG_LIGHT_SENSOR_DEVICE) += lightsensor/
 obj-$(CONFIG_MAG_SENSORS)      += magnetometer/
 
+obj-$(CONFIG_SENSOR_DEVICE)    += sensors/
+
 obj-$(CONFIG_INPUT_APMPOWER)   += apm-power.o
 obj-$(CONFIG_INPUT_KEYRESET)   += keyreset.o
diff --git a/drivers/input/sensors/Kconfig b/drivers/input/sensors/Kconfig
new file mode 100755 (executable)
index 0000000..25fea66
--- /dev/null
@@ -0,0 +1,19 @@
+#
+# all sensors drivers configuration
+#
+
+comment "handle all sensors"
+
+menuconfig SENSOR_DEVICE
+       tristate "handle gsensor,compass,gyroscope,lsensor psensor etc"
+       
+if SENSOR_DEVICE
+
+source "drivers/input/sensors/accel/Kconfig"
+source "drivers/input/sensors/compass/Kconfig"
+source "drivers/input/sensors/gyro/Kconfig"
+source "drivers/input/sensors/lsensor/Kconfig"
+source "drivers/input/sensors/psensor/Kconfig"
+source "drivers/input/sensors/temperature/Kconfig"
+
+endif
diff --git a/drivers/input/sensors/Makefile b/drivers/input/sensors/Makefile
new file mode 100755 (executable)
index 0000000..65d9b20
--- /dev/null
@@ -0,0 +1,10 @@
+# sensor drivers\r
+obj-$(CONFIG_GSENSOR_DEVICE)                   += accel/\r
+obj-$(CONFIG_COMPASS_DEVICE)                   += compass/\r
+obj-$(CONFIG_GYROSCOPE_DEVICE)                 += gyro/\r
+obj-$(CONFIG_LIGHT_DEVICE)                             += lsensor/\r
+obj-$(CONFIG_PROXIMITY_DEVICE)                 += psensor/\r
+\r
+\r
+obj-$(CONFIG_SENSOR_DEVICE)                            += sensor-i2c.o\r
+obj-$(CONFIG_SENSOR_DEVICE)                            += sensor-dev.o\r
diff --git a/drivers/input/sensors/accel/Kconfig b/drivers/input/sensors/accel/Kconfig
new file mode 100755 (executable)
index 0000000..701e6ec
--- /dev/null
@@ -0,0 +1,36 @@
+#
+# gsensor drivers configuration
+#
+
+menuconfig GSENSOR_DEVICE
+       bool "g_sensor device support"
+       help
+         Enable this to be able to choose the drivers for controlling the
+         g_sensor on some platforms, for example on PDAs.
+
+if GSENSOR_DEVICE
+config GS_MMA8452
+  bool "gsensor mma8452"
+       help     
+         To have support for your specific gsesnor you will have to
+         select the proper drivers which depend on this option.
+
+config GS_KXTIK
+  bool "gsensor kxtik"
+  help
+    To have support for your specific gsesnor you will have to
+    select the proper drivers which depend on this option.
+
+config GS_LIS3DH
+  bool "gsensor lis3dh"
+       help     
+         To have support for your specific gsesnor you will have to
+         select the proper drivers which depend on this option.
+
+config GS_BMA023
+  bool "gsensor bma023"
+  help
+    To have support for your specific gsesnor you will have to
+    select the proper drivers which depend on this option.
+endif
+
diff --git a/drivers/input/sensors/accel/Makefile b/drivers/input/sensors/accel/Makefile
new file mode 100755 (executable)
index 0000000..bb116f0
--- /dev/null
@@ -0,0 +1,3 @@
+\r
+obj-$(CONFIG_GS_KXTIK)                 += kxtik.o\r
+obj-$(CONFIG_GS_MMA8452)       += mma8452.o
\ No newline at end of file
diff --git a/drivers/input/sensors/accel/kxtik.c b/drivers/input/sensors/accel/kxtik.c
new file mode 100755 (executable)
index 0000000..1b517d5
--- /dev/null
@@ -0,0 +1,270 @@
+/* drivers/input/sensors/access/kxtik.c\r
+ *\r
+ * Copyright (C) 2012-2015 ROCKCHIP.\r
+ * Author: luowei <lw@rock-chips.com>\r
+ *\r
+ * This software is licensed under the terms of the GNU General Public\r
+ * License version 2, as published by the Free Software Foundation, and\r
+ * may be copied, distributed, and modified under those terms.\r
+ *\r
+ * This program is distributed in the hope that it will be useful,\r
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+ * GNU General Public License for more details.\r
+ *\r
+ */\r
+#include <linux/interrupt.h>\r
+#include <linux/i2c.h>\r
+#include <linux/slab.h>\r
+#include <linux/irq.h>\r
+#include <linux/miscdevice.h>\r
+#include <linux/gpio.h>\r
+#include <asm/uaccess.h>\r
+#include <asm/atomic.h>\r
+#include <linux/delay.h>\r
+#include <linux/input.h>\r
+#include <linux/workqueue.h>\r
+#include <linux/freezer.h>\r
+#include <mach/gpio.h>\r
+#include <mach/board.h> \r
+#ifdef CONFIG_HAS_EARLYSUSPEND\r
+#include <linux/earlysuspend.h>\r
+#endif\r
+#include <linux/kxtik.h>\r
+#include <linux/sensor-dev.h>\r
+\r
+#if 0\r
+#define SENSOR_DEBUG_TYPE SENSOR_TYPE_ACCEL\r
+#define DBG(x...) if(sensor->pdata->type == SENSOR_DEBUG_TYPE) printk(x)\r
+#else\r
+#define DBG(x...)\r
+#endif\r
+\r
+\r
+\r
+/****************operate according to sensor chip:start************/\r
+\r
+static int sensor_active(struct i2c_client *client, int enable, int rate)\r
+{\r
+       struct sensor_private_data *sensor =\r
+           (struct sensor_private_data *) i2c_get_clientdata(client);  \r
+       int result = 0;\r
+       int status = 0;\r
+               \r
+       sensor->ops->ctrl_data = sensor_read_reg(client, sensor->ops->ctrl_reg);\r
+       \r
+       //register setting according to chip datasheet          \r
+       if(enable)\r
+       {       \r
+               status = KXTIK_ENABLE;  //kxtik \r
+               sensor->ops->ctrl_data |= status;       \r
+       }\r
+       else\r
+       {\r
+               status = ~KXTIK_ENABLE; //kxtik\r
+               sensor->ops->ctrl_data &= status;\r
+       }\r
+\r
+       DBG("%s:reg=0x%x,reg_ctrl=0x%x,enable=%d\n",__func__,sensor->ops->ctrl_reg, sensor->ops->ctrl_data, enable);\r
+       result = sensor_write_reg(client, sensor->ops->ctrl_reg, sensor->ops->ctrl_data);\r
+       if(result)\r
+               printk("%s:fail to active sensor\n",__func__);\r
+       \r
+       return result;\r
+\r
+}\r
+\r
+static int sensor_init(struct i2c_client *client)\r
+{      \r
+       struct sensor_private_data *sensor =\r
+           (struct sensor_private_data *) i2c_get_clientdata(client);  \r
+       int result = 0;\r
+       \r
+       result = sensor->ops->active(client,0,0);\r
+       if(result)\r
+       {\r
+               printk("%s:line=%d,error\n",__func__,__LINE__);\r
+               return result;\r
+       }\r
+       \r
+       sensor->status_cur = SENSOR_OFF;\r
+       \r
+       result = sensor_write_reg(client, KXTIK_DATA_CTRL_REG, KXTIK_ODR400F);\r
+       if(result)\r
+       {\r
+               printk("%s:line=%d,error\n",__func__,__LINE__);\r
+               return result;\r
+       }\r
+\r
+       if(sensor->pdata->irq_enable)   //open interrupt\r
+       {\r
+               result = sensor_write_reg(client, KXTIK_INT_CTRL_REG1, 0x34);//enable int,active high,need read INT_REL\r
+               if(result)\r
+               {\r
+                       printk("%s:line=%d,error\n",__func__,__LINE__);\r
+                       return result;\r
+               }\r
+       }\r
+       \r
+       sensor->ops->ctrl_data = (KXTIK_RES_12BIT | KXTIK_G_2G);\r
+       result = sensor_write_reg(client, sensor->ops->ctrl_reg, sensor->ops->ctrl_data);\r
+       if(result)\r
+       {\r
+               printk("%s:line=%d,error\n",__func__,__LINE__);\r
+               return result;\r
+       }\r
+       \r
+       return result;\r
+}\r
+\r
+static int sensor_convert_data(struct i2c_client *client, char high_byte, char low_byte)\r
+{\r
+    s64 result;\r
+       struct sensor_private_data *sensor =\r
+           (struct sensor_private_data *) i2c_get_clientdata(client);  \r
+       //int precision = sensor->ops->precision;\r
+       switch (sensor->devid) {        \r
+               case KXTIK_DEVID:               \r
+                       result = (((int)high_byte << 8) | ((int)low_byte ))>>4;\r
+                       if (result < KXTIK_BOUNDARY)\r
+                               result = result* KXTIK_GRAVITY_STEP;\r
+               else\r
+                               result = ~( ((~result & (0x7fff>>(16-KXTIK_PRECISION)) ) + 1) \r
+                                               * KXTIK_GRAVITY_STEP) + 1;\r
+                       break;\r
+\r
+               default:\r
+                       printk(KERN_ERR "%s: devid wasn't set correctly\n",__func__);\r
+                       return -EFAULT;\r
+    }\r
+\r
+    return (int)result;\r
+}\r
+\r
+static int gsensor_report_value(struct i2c_client *client, struct sensor_axis *axis)\r
+{\r
+       struct sensor_private_data *sensor =\r
+               (struct sensor_private_data *) i2c_get_clientdata(client);      \r
+\r
+       /* Report acceleration sensor information */\r
+       input_report_abs(sensor->input_dev, ABS_X, axis->x);\r
+       input_report_abs(sensor->input_dev, ABS_Y, axis->y);\r
+       input_report_abs(sensor->input_dev, ABS_Z, axis->z);\r
+       input_sync(sensor->input_dev);\r
+       DBG("Gsensor x==%d  y==%d z==%d\n",axis->x,axis->y,axis->z);\r
+\r
+       return 0;\r
+}\r
+\r
+#define GSENSOR_MIN  10\r
+static int sensor_report_value(struct i2c_client *client, unsigned char *buffer, int length)\r
+{\r
+       struct sensor_private_data *sensor =\r
+                       (struct sensor_private_data *) i2c_get_clientdata(client);      \r
+       struct sensor_platform_data *pdata = sensor->pdata;\r
+       int ret = 0;\r
+       int x,y,z;\r
+       struct sensor_axis axis;        \r
+       char buffer[6] = {0};   \r
+       \r
+       if(sensor->ops->read_len < 6)   //sensor->ops->read_len = 6\r
+       {\r
+               printk("%s:lenth is error,len=%d\n",__func__,sensor->ops->read_len);\r
+               return -1;\r
+       }\r
+       \r
+       memset(buffer, 0, 6);\r
+       \r
+       /* Data bytes from hardware xL, xH, yL, yH, zL, zH */   \r
+       do {\r
+               *buffer = sensor->ops->read_reg;\r
+               ret = sensor_rx_data(client, buffer, sensor->ops->read_len);\r
+               if (ret < 0)\r
+               return ret;\r
+       } while (0);\r
+\r
+       //this gsensor need 6 bytes buffer\r
+       x = sensor_convert_data(sensor->client, buffer[1], buffer[0]);  //buffer[1]:high bit \r
+       y = sensor_convert_data(sensor->client, buffer[3], buffer[2]);\r
+       z = sensor_convert_data(sensor->client, buffer[5], buffer[4]);          \r
+\r
+       axis.x = (pdata->orientation[0])*x + (pdata->orientation[1])*y + (pdata->orientation[2])*z;\r
+       axis.y = (pdata->orientation[3])*x + (pdata->orientation[4])*y + (pdata->orientation[5])*z;     \r
+       axis.z = (pdata->orientation[6])*x + (pdata->orientation[7])*y + (pdata->orientation[8])*z;\r
+\r
+       DBG( "%s: axis = %d  %d  %d \n", __func__, axis.x, axis.y, axis.z);\r
+\r
+       //Report event  only while value is changed to save some power\r
+       if((abs(sensor->axis.x - axis.x) > GSENSOR_MIN) || (abs(sensor->axis.y - axis.y) > GSENSOR_MIN) || (abs(sensor->axis.z - axis.z) > GSENSOR_MIN))\r
+       {\r
+               gsensor_report_value(client, &axis);\r
+\r
+               /* »¥³âµØ»º´æÊý¾Ý. */\r
+               mutex_lock(&(sensor->data_mutex) );\r
+               sensor->axis = axis;\r
+               mutex_unlock(&(sensor->data_mutex) );\r
+       }\r
+\r
+       if((sensor->pdata->irq_enable)&& (sensor->ops->int_status_reg >= 0))    //read sensor intterupt status register\r
+       {\r
+               \r
+               ret= sensor_read_reg(client, sensor->ops->int_status_reg);\r
+               if(ret)\r
+               {\r
+                       printk("%s:fail to clear sensor int status,ret=0x%x\n",__func__,ret);\r
+               }\r
+       }\r
+       \r
+       return ret;\r
+}\r
+\r
+struct sensor_operate gsensor_ops = {\r
+       .name                           = "kxtik",\r
+       .type                           = SENSOR_TYPE_ACCEL,            //sensor type and it should be correct\r
+       .id_i2c                         = ACCEL_ID_KXTIK,               //i2c id number\r
+       .read_reg                       = KXTIK_XOUT_L,                 //read data\r
+       .read_len                       = 6,                            //data length\r
+       .id_reg                         = KXTIK_WHO_AM_I,               //read device id from this register\r
+       .id_data                        = KXTIK_DEVID,                  //device id\r
+       .precision                      = KXTIK_PRECISION,              //12 bits\r
+       .ctrl_reg                       = KXTIK_CTRL_REG1,              //enable or disable \r
+       .int_status_reg                 = KXTIK_INT_REL,                //intterupt status register\r
+       .range                          = {-KXTIK_RANGE,KXTIK_RANGE},   //range\r
+       .trig                           = IRQF_TRIGGER_LOW|IRQF_ONESHOT,                \r
+       .active                         = sensor_active,        \r
+       .init                           = sensor_init,\r
+       .report                         = sensor_report_value,\r
+};\r
+\r
+/****************operate according to sensor chip:end************/\r
+\r
+//function name should not be changed\r
+struct sensor_operate *gsensor_get_ops(void)\r
+{\r
+       return &gsensor_ops;\r
+}\r
+\r
+EXPORT_SYMBOL(gsensor_get_ops);\r
+\r
+static int __init gsensor_init(void)\r
+{\r
+       struct sensor_operate *ops = gsensor_get_ops();\r
+       int result = 0;\r
+       int type = ops->type;\r
+       result = sensor_register_slave(type, NULL, NULL, gsensor_get_ops);\r
+       printk("%s\n",__func__);\r
+       return result;\r
+}\r
+\r
+static void __exit gsensor_exit(void)\r
+{\r
+       struct sensor_operate *ops = gsensor_get_ops();\r
+       int type = ops->type;\r
+       sensor_unregister_slave(type, NULL, NULL, gsensor_get_ops);\r
+}\r
+\r
+\r
+module_init(gsensor_init);\r
+module_exit(gsensor_exit);\r
+\r
+\r
diff --git a/drivers/input/sensors/accel/mma8452.c b/drivers/input/sensors/accel/mma8452.c
new file mode 100755 (executable)
index 0000000..c400161
--- /dev/null
@@ -0,0 +1,308 @@
+/* drivers/input/sensors/access/mma8452.c\r
+ *\r
+ * Copyright (C) 2012-2015 ROCKCHIP.\r
+ * Author: luowei <lw@rock-chips.com>\r
+ *\r
+ * This software is licensed under the terms of the GNU General Public\r
+ * License version 2, as published by the Free Software Foundation, and\r
+ * may be copied, distributed, and modified under those terms.\r
+ *\r
+ * This program is distributed in the hope that it will be useful,\r
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+ * GNU General Public License for more details.\r
+ *\r
+ */\r
+#include <linux/interrupt.h>\r
+#include <linux/i2c.h>\r
+#include <linux/slab.h>\r
+#include <linux/irq.h>\r
+#include <linux/miscdevice.h>\r
+#include <linux/gpio.h>\r
+#include <asm/uaccess.h>\r
+#include <asm/atomic.h>\r
+#include <linux/delay.h>\r
+#include <linux/input.h>\r
+#include <linux/workqueue.h>\r
+#include <linux/freezer.h>\r
+#include <mach/gpio.h>\r
+#include <mach/board.h> \r
+#ifdef CONFIG_HAS_EARLYSUSPEND\r
+#include <linux/earlysuspend.h>\r
+#endif\r
+#include <linux/mma8452.h>\r
+#include <linux/sensor-dev.h>\r
+\r
+#if 0\r
+#define SENSOR_DEBUG_TYPE SENSOR_TYPE_ACCEL\r
+#define DBG(x...) if(sensor->pdata->type == SENSOR_DEBUG_TYPE) printk(x)\r
+#else\r
+#define DBG(x...)\r
+#endif\r
+\r
+\r
+#define MMA8451_DEVID          0x1a\r
+#define MMA8452_DEVID          0x2a\r
+#define MMA8453_DEVID          0x3a\r
+\r
+#define MMA8452_ENABLE         1\r
+\r
+\r
+/****************operate according to sensor chip:start************/\r
+\r
+static int sensor_active(struct i2c_client *client, int enable, int rate)\r
+{\r
+       struct sensor_private_data *sensor =\r
+           (struct sensor_private_data *) i2c_get_clientdata(client);  \r
+       int result = 0;\r
+       int status = 0;\r
+               \r
+       sensor->ops->ctrl_data = sensor_read_reg(client, sensor->ops->ctrl_reg);\r
+       \r
+       //register setting according to chip datasheet          \r
+       if(enable)\r
+       {       \r
+               status = MMA8452_ENABLE;        //mma8452\r
+               sensor->ops->ctrl_data |= status;       \r
+       }\r
+       else\r
+       {\r
+               status = ~MMA8452_ENABLE;       //mma8452\r
+               sensor->ops->ctrl_data &= status;\r
+       }\r
+\r
+       DBG("%s:reg=0x%x,reg_ctrl=0x%x,enable=%d\n",__func__,sensor->ops->ctrl_reg, sensor->ops->ctrl_data, enable);\r
+       result = sensor_write_reg(client, sensor->ops->ctrl_reg, sensor->ops->ctrl_data);\r
+       if(result)\r
+               printk("%s:fail to active sensor\n",__func__);\r
+       \r
+       return result;\r
+\r
+}\r
+\r
+static int sensor_init(struct i2c_client *client)\r
+{\r
+       int tmp;\r
+       int ret = 0;\r
+       struct sensor_private_data *sensor =\r
+           (struct sensor_private_data *) i2c_get_clientdata(client);  \r
+       \r
+       ret = sensor->ops->active(client,0,0);\r
+       if(ret)\r
+       {\r
+               printk("%s:line=%d,error\n",__func__,__LINE__);\r
+               return ret;\r
+       }\r
+       \r
+       sensor->status_cur = SENSOR_OFF;\r
+\r
+       /* disable FIFO  FMODE = 0*/\r
+       ret = sensor_write_reg(client,MMA8452_REG_F_SETUP,0);\r
+       DBG("%s: MMA8452_REG_F_SETUP:%x\n",__func__, sensor_read_reg(client,MMA8452_REG_F_SETUP));\r
+\r
+       /* set full scale range to 2g */\r
+       ret = sensor_write_reg(client,MMA8452_REG_XYZ_DATA_CFG,0);\r
+       DBG("%s: MMA8452_REG_XYZ_DATA_CFG:%x\n",__func__, sensor_read_reg(client,MMA8452_REG_XYZ_DATA_CFG));\r
+\r
+       /* set bus 8bit/14bit(FREAD = 1,FMODE = 0) ,data rate*/\r
+       tmp = (MMA8452_RATE_12P5<< MMA8452_RATE_SHIFT) | FREAD_MASK;\r
+       ret = sensor_write_reg(client,MMA8452_REG_CTRL_REG1,tmp);\r
+\r
+       sensor->ops->ctrl_data = tmp;\r
+       \r
+       DBG("mma8452 MMA8452_REG_CTRL_REG1:%x\n",sensor_read_reg(client,MMA8452_REG_CTRL_REG1));\r
+       \r
+       DBG("mma8452 MMA8452_REG_SYSMOD:%x\n",sensor_read_reg(client,MMA8452_REG_SYSMOD));\r
+\r
+       ret = sensor_write_reg(client,MMA8452_REG_CTRL_REG3,5);\r
+       DBG("mma8452 MMA8452_REG_CTRL_REG3:%x\n",sensor_read_reg(client,MMA8452_REG_CTRL_REG3));\r
+       \r
+       ret = sensor_write_reg(client,MMA8452_REG_CTRL_REG4,1);\r
+       DBG("mma8452 MMA8452_REG_CTRL_REG4:%x\n",sensor_read_reg(client,MMA8452_REG_CTRL_REG4));\r
+\r
+       ret = sensor_write_reg(client,MMA8452_REG_CTRL_REG5,1);\r
+       DBG("mma8452 MMA8452_REG_CTRL_REG5:%x\n",sensor_read_reg(client,MMA8452_REG_CTRL_REG5));        \r
+\r
+       DBG("mma8452 MMA8452_REG_SYSMOD:%x\n",sensor_read_reg(client,MMA8452_REG_SYSMOD));\r
+\r
+       return ret;\r
+}\r
+\r
+static int sensor_convert_data(struct i2c_client *client, char high_byte, char low_byte)\r
+{\r
+    s64 result;\r
+       struct sensor_private_data *sensor =\r
+           (struct sensor_private_data *) i2c_get_clientdata(client);  \r
+       //int precision = sensor->ops->precision;\r
+       switch (sensor->devid) {\r
+               case MMA8451_DEVID:     \r
+                       swap(high_byte,low_byte);\r
+                       result = ((int)high_byte << (MMA8451_PRECISION-8)) \r
+                                       | ((int)low_byte >> (16-MMA8451_PRECISION));\r
+                       if (result < MMA8451_BOUNDARY)\r
+                               result = result* MMA8451_GRAVITY_STEP;\r
+                       else\r
+                               result = ~( ((~result & (0x7fff>>(16-MMA8451_PRECISION)) ) + 1) \r
+                                               * MMA8451_GRAVITY_STEP) + 1;\r
+                       break;\r
+\r
+               case MMA8452_DEVID:                     \r
+                       swap(high_byte,low_byte);\r
+                       result = ((int)high_byte << (MMA8452_PRECISION-8)) \r
+                                       | ((int)low_byte >> (16-MMA8452_PRECISION));\r
+                       if (result < MMA8452_BOUNDARY)\r
+                               result = result* MMA8452_GRAVITY_STEP;\r
+                       else\r
+                               result = ~( ((~result & (0x7fff>>(16-MMA8452_PRECISION)) ) + 1) \r
+                                               * MMA8452_GRAVITY_STEP) + 1;\r
+                       break;\r
+                       \r
+               case MMA8453_DEVID:             \r
+                       swap(high_byte,low_byte);\r
+                       result = ((int)high_byte << (MMA8453_PRECISION-8)) \r
+                                       | ((int)low_byte >> (16-MMA8453_PRECISION));\r
+                       if (result < MMA8453_BOUNDARY)\r
+                               result = result* MMA8453_GRAVITY_STEP;\r
+                       else\r
+                               result = ~( ((~result & (0x7fff>>(16-MMA8453_PRECISION)) ) + 1) \r
+                                               * MMA8453_GRAVITY_STEP) + 1;\r
+                       break;\r
+\r
+               default:\r
+                       printk(KERN_ERR "%s: devid wasn't set correctly\n",__func__);\r
+                       return -EFAULT;\r
+    }\r
+\r
+    return (int)result;\r
+}\r
+\r
+static int gsensor_report_value(struct i2c_client *client, struct sensor_axis *axis)\r
+{\r
+       struct sensor_private_data *sensor =\r
+           (struct sensor_private_data *) i2c_get_clientdata(client);  \r
+\r
+       /* Report acceleration sensor information */\r
+       input_report_abs(sensor->input_dev, ABS_X, axis->x);\r
+       input_report_abs(sensor->input_dev, ABS_Y, axis->y);\r
+       input_report_abs(sensor->input_dev, ABS_Z, axis->z);\r
+       input_sync(sensor->input_dev);\r
+       DBG("Gsensor x==%d  y==%d z==%d\n",axis->x,axis->y,axis->z);\r
+\r
+       return 0;\r
+}\r
+\r
+#define GSENSOR_MIN            10\r
+static int sensor_report_value(struct i2c_client *client)\r
+{\r
+       struct sensor_private_data *sensor =\r
+               (struct sensor_private_data *) i2c_get_clientdata(client);      \r
+       struct sensor_platform_data *pdata = sensor->pdata;\r
+       int ret = 0;\r
+       int x,y,z;\r
+       struct sensor_axis axis;\r
+       char buffer[6] = {0};   \r
+                       \r
+       if(sensor->ops->read_len < 6)   //sensor->ops->read_len = 6\r
+       {\r
+               printk("%s:lenth is error,len=%d\n",__func__,sensor->ops->read_len);\r
+               return -1;\r
+       }\r
+       \r
+       memset(buffer, 0, 6);\r
+       \r
+       /* Data bytes from hardware xL, xH, yL, yH, zL, zH */   \r
+       do {\r
+               *buffer = sensor->ops->read_reg;\r
+               ret = sensor_rx_data(client, buffer, sensor->ops->read_len);\r
+               if (ret < 0)\r
+               return ret;\r
+       } while (0);\r
+\r
+\r
+       //this gsensor need 6 bytes buffer\r
+       x = sensor_convert_data(sensor->client, buffer[1], buffer[0]);  //buffer[1]:high bit \r
+       y = sensor_convert_data(sensor->client, buffer[3], buffer[2]);\r
+       z = sensor_convert_data(sensor->client, buffer[5], buffer[4]);          \r
+\r
+       axis.x = (pdata->orientation[0])*x + (pdata->orientation[1])*y + (pdata->orientation[2])*z;\r
+       axis.y = (pdata->orientation[3])*x + (pdata->orientation[4])*y + (pdata->orientation[5])*z; \r
+       axis.z = (pdata->orientation[6])*x + (pdata->orientation[7])*y + (pdata->orientation[8])*z;\r
+\r
+       DBG( "%s: axis = %d  %d  %d \n", __func__, axis.x, axis.y, axis.z);\r
+\r
+       //Report event only while value is changed to save some power\r
+       if((abs(sensor->axis.x - axis.x) > GSENSOR_MIN) || (abs(sensor->axis.y - axis.y) > GSENSOR_MIN) || (abs(sensor->axis.z - axis.z) > GSENSOR_MIN))\r
+       {\r
+               gsensor_report_value(client, &axis);\r
+\r
+               /* »¥³âµØ»º´æÊý¾Ý. */\r
+               mutex_lock(&(sensor->data_mutex) );\r
+               sensor->axis = axis;\r
+               mutex_unlock(&(sensor->data_mutex) );\r
+       }\r
+\r
+       if((sensor->pdata->irq_enable)&& (sensor->ops->int_status_reg >= 0))    //read sensor intterupt status register\r
+       {\r
+               \r
+               ret= sensor_read_reg(client, sensor->ops->int_status_reg);\r
+               if(ret)\r
+               {\r
+                       printk("%s:fail to clear sensor int status,ret=0x%x\n",__func__,ret);\r
+               }\r
+       }\r
+       \r
+       return ret;\r
+}\r
+\r
+\r
+struct sensor_operate gsensor_ops = {\r
+       .name                           = "mma8452",\r
+       .type                           = SENSOR_TYPE_ACCEL,                    //sensor type and it should be correct\r
+       .id_i2c                         = ACCEL_ID_MMA845X,                     //i2c id number\r
+       .read_reg                       = MMA8452_REG_X_OUT_MSB,                //read data\r
+       .read_len                       = 6,                                    //data length\r
+       .id_reg                         = MMA8452_REG_WHO_AM_I,                 //read device id from this register\r
+       .id_data                        = MMA8452_DEVID,                        //device id\r
+       .precision                      = MMA8452_PRECISION,                    //12 bit\r
+       .ctrl_reg                       = MMA8452_REG_CTRL_REG1,                //enable or disable     \r
+       .int_status_reg                 = MMA8452_REG_INTSRC,                   //intterupt status register\r
+       .range                          = {-MMA845X_RANGE,MMA845X_RANGE},       //range\r
+       .trig                           = IRQF_TRIGGER_LOW|IRQF_ONESHOT,                \r
+       .active                         = sensor_active,        \r
+       .init                           = sensor_init,\r
+       .report                         = sensor_report_value,\r
+};\r
+\r
+/****************operate according to sensor chip:end************/\r
+\r
+//function name should not be changed\r
+struct sensor_operate *gsensor_get_ops(void)\r
+{\r
+       return &gsensor_ops;\r
+}\r
+\r
+EXPORT_SYMBOL(gsensor_get_ops);\r
+\r
+static int __init gsensor_init(void)\r
+{\r
+       struct sensor_operate *ops = gsensor_get_ops();\r
+       int result = 0;\r
+       int type = ops->type;\r
+       result = sensor_register_slave(type, NULL, NULL, gsensor_get_ops);      \r
+       printk("%s\n",__func__);\r
+       return result;\r
+}\r
+\r
+static void __exit gsensor_exit(void)\r
+{\r
+       struct sensor_operate *ops = gsensor_get_ops();\r
+       int type = ops->type;\r
+       sensor_unregister_slave(type, NULL, NULL, gsensor_get_ops);\r
+}\r
+\r
+\r
+module_init(gsensor_init);\r
+module_exit(gsensor_exit);\r
+\r
+\r
+\r
diff --git a/drivers/input/sensors/compass/Kconfig b/drivers/input/sensors/compass/Kconfig
new file mode 100755 (executable)
index 0000000..72ab06c
--- /dev/null
@@ -0,0 +1,37 @@
+#
+# Magnetometer drivers configuration
+#
+
+menuconfig COMPASS_DEVICE
+       bool "Magnetometer sensors"
+       help
+         Say Y here, and a list of Magnetometer sensors drivers will be displayed.
+         Everything that didn't fit into the other categories is here. This option
+         doesn't affect the kernel.
+
+         If unsure, say Y.
+
+if COMPASS_DEVICE
+
+config COMPASS_AK8975
+  tristate "Asahi Kasei AK8975 3-Axis Magnetometer"
+  depends on I2C
+  help
+  Say yes here to build support for Asahi Kasei AK8975 3-Axis
+  Magnetometer.
+
+  To compile this driver as a module, choose M here: the module
+  will be called ak8975.
+
+config COMPASS_MMC328X
+  tristate "Mmc328x 3-Axis Magnetometer"
+  depends on I2C
+  help
+  Say yes here to build support for mmc3280 3-Axis
+  Magnetometer.
+
+  To compile this driver as a module, choose M here: the module
+  will be called mmc3280. 
+
+endif
+
diff --git a/drivers/input/sensors/compass/Makefile b/drivers/input/sensors/compass/Makefile
new file mode 100755 (executable)
index 0000000..dfd09bf
--- /dev/null
@@ -0,0 +1,6 @@
+#
+# Makefile for industrial I/O Magnetometer sensors
+#
+obj-$(CONFIG_COMPASS_AK8975) := ak8975.o 
+obj-$(CONFIG_COMPASS_AK8973) := ak8973.o 
+obj-$(CONFIG_COMPASS_MMC328X) := mmc328x.o 
\ No newline at end of file
diff --git a/drivers/input/sensors/compass/ak8975.c b/drivers/input/sensors/compass/ak8975.c
new file mode 100755 (executable)
index 0000000..18af827
--- /dev/null
@@ -0,0 +1,753 @@
+/* drivers/input/sensors/access/akm8975.c\r
+ *\r
+ * Copyright (C) 2012-2015 ROCKCHIP.\r
+ * Author: luowei <lw@rock-chips.com>\r
+ *\r
+ * This software is licensed under the terms of the GNU General Public\r
+ * License version 2, as published by the Free Software Foundation, and\r
+ * may be copied, distributed, and modified under those terms.\r
+ *\r
+ * This program is distributed in the hope that it will be useful,\r
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+ * GNU General Public License for more details.\r
+ *\r
+ */\r
+#include <linux/interrupt.h>\r
+#include <linux/i2c.h>\r
+#include <linux/slab.h>\r
+#include <linux/irq.h>\r
+#include <linux/miscdevice.h>\r
+#include <linux/gpio.h>\r
+#include <asm/uaccess.h>\r
+#include <asm/atomic.h>\r
+#include <linux/delay.h>\r
+#include <linux/input.h>\r
+#include <linux/workqueue.h>\r
+#include <linux/freezer.h>\r
+#include <mach/gpio.h>\r
+#include <mach/board.h> \r
+#ifdef CONFIG_HAS_EARLYSUSPEND\r
+#include <linux/earlysuspend.h>\r
+#endif\r
+#include <linux/akm8975.h>\r
+#include <linux/sensor-dev.h>\r
+\r
+#define SENSOR_DATA_SIZE               8\r
+\r
+#if 0\r
+#define SENSOR_DEBUG_TYPE SENSOR_TYPE_COMPASS\r
+#define DBG(x...) if(sensor->pdata->type == SENSOR_DEBUG_TYPE) printk(x)\r
+#else\r
+#define DBG(x...)\r
+#endif\r
+\r
+\r
+\r
+#define AK8975_DEVICE_ID               0x48\r
+static struct i2c_client *this_client;\r
+\r
+static atomic_t m_flag;\r
+static atomic_t a_flag;\r
+static atomic_t mv_flag;\r
+static atomic_t open_flag;\r
+static short akmd_delay = 100;\r
+static DECLARE_WAIT_QUEUE_HEAD(open_wq);\r
+\r
+\r
+/****************operate according to sensor chip:start************/\r
+\r
+static int sensor_active(struct i2c_client *client, int enable, int rate)\r
+{\r
+       struct sensor_private_data *sensor =\r
+           (struct sensor_private_data *) i2c_get_clientdata(client);  \r
+       int result = 0;\r
+       int status = 0;\r
+               \r
+       sensor->ops->ctrl_data = sensor_read_reg(client, sensor->ops->ctrl_reg);\r
+       \r
+       //register setting according to chip datasheet          \r
+       if(enable)\r
+       {       \r
+               status = AK8975_MODE_SNG_MEASURE;\r
+               sensor->ops->ctrl_data |= status;       \r
+       }\r
+       else\r
+       {\r
+               status = ~AK8975_MODE_SNG_MEASURE;\r
+               sensor->ops->ctrl_data &= status;\r
+       }\r
+\r
+       DBG("%s:reg=0x%x,reg_ctrl=0x%x,enable=%d\n",__func__,sensor->ops->ctrl_reg, sensor->ops->ctrl_data, enable);\r
+       result = sensor_write_reg(client, sensor->ops->ctrl_reg, sensor->ops->ctrl_data);\r
+       if(result)\r
+               printk("%s:fail to active sensor\n",__func__);\r
+       \r
+       return result;\r
+\r
+}\r
+\r
+static int sensor_init(struct i2c_client *client)\r
+{      \r
+       struct sensor_private_data *sensor =\r
+           (struct sensor_private_data *) i2c_get_clientdata(client);  \r
+       int result = 0;\r
+\r
+       this_client = client;   \r
+\r
+       result = sensor->ops->active(client,0,0);\r
+       if(result)\r
+       {\r
+               printk("%s:line=%d,error\n",__func__,__LINE__);\r
+               return result;\r
+       }\r
+       \r
+       sensor->status_cur = SENSOR_OFF;\r
+       \r
+       sensor->ops->ctrl_data = 0;\r
+       result = sensor_write_reg(client, sensor->ops->ctrl_reg, sensor->ops->ctrl_data);\r
+       if(result)\r
+       {\r
+               printk("%s:line=%d,error\n",__func__,__LINE__);\r
+               return result;\r
+       }\r
+\r
+       DBG("%s:status_cur=%d\n",__func__, sensor->status_cur);\r
+       return result;\r
+}\r
+\r
+static int sensor_report_value(struct i2c_client *client)\r
+{\r
+       struct sensor_private_data *sensor =\r
+               (struct sensor_private_data *) i2c_get_clientdata(client);      \r
+       char buffer[8] = {0};   \r
+       unsigned char *stat;\r
+       unsigned char *stat2;   \r
+       int ret = 0;    \r
+#ifdef SENSOR_DEBUG_TYPE       \r
+       int i;\r
+#endif                 \r
+       if(sensor->ops->read_len < 8)   //sensor->ops->read_len = 8\r
+       {\r
+               printk("%s:lenth is error,len=%d\n",__func__,sensor->ops->read_len);\r
+               return -1;\r
+       }\r
+       \r
+       memset(buffer, 0, 8);\r
+       \r
+       /* Data bytes from hardware xL, xH, yL, yH, zL, zH */   \r
+       do {\r
+               *buffer = sensor->ops->read_reg;\r
+               ret = sensor_rx_data(client, buffer, sensor->ops->read_len);\r
+               if (ret < 0)\r
+               return ret;\r
+       } while (0);\r
+\r
+       stat = &buffer[0];\r
+       stat2 = &buffer[7];\r
+       \r
+       /*\r
+        * ST : data ready -
+        * Measurement has been completed and data is ready to be read.
+        */\r
+       if ((*stat & 0x01) != 0x01) {\r
+               DBG(KERN_ERR "%s:ST is not set\n",__func__);\r
+               return -1;\r
+       }\r
+
+       /*
+        * ST2 : data error -
+        * occurs when data read is started outside of a readable period;
+        * data read would not be correct.
+        * Valid in continuous measurement mode only.
+        * In single measurement mode this error should not occour but we
+        * stil account for it and return an error, since the data would be
+        * corrupted.
+        * DERR bit is self-clearing when ST2 register is read.
+        */
+       if (*stat2 & 0x04)\r
+       {\r
+               DBG(KERN_ERR "%s:compass data error\n",__func__);\r
+               return -2;\r
+       }\r
+       \r
+       /*
+        * ST2 : overflow -
+        * the sum of the absolute values of all axis |X|+|Y|+|Z| < 2400uT.
+        * This is likely to happen in presence of an external magnetic
+        * disturbance; it indicates, the sensor data is incorrect and should
+        * be ignored.
+        * An error is returned.
+        * HOFL bit clears when a new measurement starts.
+        */
+       if (*stat2 & 0x08)\r
+       {       \r
+               DBG(KERN_ERR "%s:compass data overflow\n",__func__);\r
+               return -3;\r
+       }\r
+       \r
+       /* »¥³âµØ»º´æÊý¾Ý. */\r
+       mutex_lock(&sensor->data_mutex);        \r
+       memcpy(sensor->sensor_data, buffer, sensor->ops->read_len);\r
+       mutex_unlock(&sensor->data_mutex);\r
+#ifdef SENSOR_DEBUG_TYPE       \r
+       DBG("%s:",__func__);\r
+       for(i=0; i<sensor->ops->read_len; i++)\r
+               DBG("%d,",buffer[i]);\r
+       DBG("\n");\r
+#endif \r
+\r
+       if((sensor->pdata->irq_enable)&& (sensor->ops->int_status_reg >= 0))    //read sensor intterupt status register\r
+       {\r
+               \r
+               ret= sensor_read_reg(client, sensor->ops->int_status_reg);\r
+               if(ret)\r
+               {\r
+                       printk("%s:fail to clear sensor int status,ret=0x%x\n",__func__,ret);\r
+               }\r
+       }\r
+       \r
+       return ret;\r
+}\r
+\r
+static void compass_set_YPR(short *rbuf)\r
+{\r
+       struct sensor_private_data *sensor =\r
+           (struct sensor_private_data *) i2c_get_clientdata(this_client);     \r
+       \r
+       /* Report magnetic sensor information */\r
+       if (atomic_read(&m_flag)) {\r
+               input_report_abs(sensor->input_dev, ABS_RX, rbuf[0]);\r
+               input_report_abs(sensor->input_dev, ABS_RY, rbuf[1]);\r
+               input_report_abs(sensor->input_dev, ABS_RZ, rbuf[2]);\r
+               input_report_abs(sensor->input_dev, ABS_RUDDER, rbuf[4]);\r
+               DBG("%s:m_flag:x=%d,y=%d,z=%d,RUDDER=%d\n",__func__,rbuf[0], rbuf[1], rbuf[2], rbuf[4]);\r
+       }\r
+       \r
+       /* Report acceleration sensor information */\r
+       if (atomic_read(&a_flag)) {\r
+               input_report_abs(sensor->input_dev, ABS_X, rbuf[6]);\r
+               input_report_abs(sensor->input_dev, ABS_Y, rbuf[7]);\r
+               input_report_abs(sensor->input_dev, ABS_Z, rbuf[8]);\r
+               input_report_abs(sensor->input_dev, ABS_WHEEL, rbuf[5]);\r
+               \r
+               DBG("%s:a_flag:x=%d,y=%d,z=%d,WHEEL=%d\n",__func__,rbuf[6], rbuf[7], rbuf[8], rbuf[5]);\r
+       }\r
+       \r
+       /* Report magnetic vector information */\r
+       if (atomic_read(&mv_flag)) {\r
+               input_report_abs(sensor->input_dev, ABS_HAT0X, rbuf[9]);\r
+               input_report_abs(sensor->input_dev, ABS_HAT0Y, rbuf[10]);\r
+               input_report_abs(sensor->input_dev, ABS_BRAKE, rbuf[11]);\r
+       \r
+               DBG("%s:mv_flag:x=%d,y=%d,BRAKE=%d\n",__func__,rbuf[9], rbuf[10], rbuf[11]);\r
+       }\r
+       \r
+       input_sync(sensor->input_dev);\r
+}\r
+\r
+\r
+\r
+static int compass_aot_open(struct inode *inode, struct file *file)\r
+{\r
+#ifdef SENSOR_DEBUG_TYPE\r
+       struct sensor_private_data* sensor =\r
+                       (struct sensor_private_data *)i2c_get_clientdata(this_client);\r
+#endif\r
+       int result = 0;\r
+       int flag = 0;\r
+       flag = atomic_read(&open_flag);\r
+       if(!flag)\r
+       {       \r
+               atomic_set(&open_flag, 1);\r
+               wake_up(&open_wq);\r
+       }\r
+\r
+       DBG("%s\n", __func__);\r
+       return result;\r
+}\r
+\r
+\r
+static int compass_aot_release(struct inode *inode, struct file *file)\r
+{      \r
+#ifdef SENSOR_DEBUG_TYPE\r
+       struct sensor_private_data* sensor =\r
+                       (struct sensor_private_data *)i2c_get_clientdata(this_client);  \r
+#endif\r
+       //struct i2c_client *client = this_client;\r
+       int result = 0;\r
+       int flag = 0;\r
+       flag = atomic_read(&open_flag);\r
+       if(flag)\r
+       {\r
+               atomic_set(&open_flag, 0);\r
+               wake_up(&open_wq);      \r
+       }\r
+       \r
+       DBG("%s\n", __func__);\r
+       return result;\r
+}\r
+\r
+\r
+/* ioctl - I/O control */\r
+static long compass_aot_ioctl(struct file *file,\r
+                         unsigned int cmd, unsigned long arg)\r
+{\r
+#ifdef SENSOR_DEBUG_TYPE\r
+       struct sensor_private_data* sensor = \r
+                       (struct sensor_private_data *)i2c_get_clientdata(this_client);  \r
+#endif\r
+       void __user *argp = (void __user *)arg;\r
+       int result = 0;\r
+       short flag;\r
+       \r
+       switch (cmd) {\r
+               case ECS_IOCTL_APP_SET_MFLAG:\r
+               case ECS_IOCTL_APP_SET_AFLAG:\r
+               case ECS_IOCTL_APP_SET_MVFLAG:\r
+                       if (copy_from_user(&flag, argp, sizeof(flag))) {\r
+                               return -EFAULT;\r
+                       }\r
+                       if (flag < 0 || flag > 1) {\r
+                               return -EINVAL;\r
+                       }\r
+                       break;\r
+               case ECS_IOCTL_APP_SET_DELAY:\r
+                       if (copy_from_user(&flag, argp, sizeof(flag))) {\r
+                               return -EFAULT;\r
+                       }\r
+                       break;\r
+               default:\r
+                       break;\r
+       }\r
+       \r
+       switch (cmd) {\r
+               case ECS_IOCTL_APP_SET_MFLAG:   \r
+                       atomic_set(&m_flag, flag);                      \r
+                       DBG("%s:ECS_IOCTL_APP_SET_MFLAG,flag=%d\n", __func__,flag);\r
+                       break;\r
+               case ECS_IOCTL_APP_GET_MFLAG:           \r
+                       flag = atomic_read(&m_flag);\r
+                       DBG("%s:ECS_IOCTL_APP_GET_MFLAG,flag=%d\n", __func__,flag);\r
+                       break;\r
+               case ECS_IOCTL_APP_SET_AFLAG:   \r
+                       atomic_set(&a_flag, flag);              \r
+                       DBG("%s:ECS_IOCTL_APP_SET_AFLAG,flag=%d\n", __func__,flag);\r
+                       break;\r
+               case ECS_IOCTL_APP_GET_AFLAG:\r
+                       flag = atomic_read(&a_flag);            \r
+                       DBG("%s:ECS_IOCTL_APP_GET_AFLAG,flag=%d\n", __func__,flag);\r
+                       break;\r
+               case ECS_IOCTL_APP_SET_MVFLAG:  \r
+                       atomic_set(&mv_flag, flag);             \r
+                       DBG("%s:ECS_IOCTL_APP_SET_MVFLAG,flag=%d\n", __func__,flag);\r
+                       break;\r
+               case ECS_IOCTL_APP_GET_MVFLAG:          \r
+                       flag = atomic_read(&mv_flag);           \r
+                       DBG("%s:ECS_IOCTL_APP_GET_MVFLAG,flag=%d\n", __func__,flag);\r
+                       break;\r
+               case ECS_IOCTL_APP_SET_DELAY:\r
+                       akmd_delay = flag;\r
+                       break;\r
+               case ECS_IOCTL_APP_GET_DELAY:\r
+                       flag = akmd_delay;\r
+                       break;\r
+               default:\r
+                       return -ENOTTY;\r
+       }\r
+       \r
+       switch (cmd) {\r
+               case ECS_IOCTL_APP_GET_MFLAG:\r
+               case ECS_IOCTL_APP_GET_AFLAG:\r
+               case ECS_IOCTL_APP_GET_MVFLAG:\r
+               case ECS_IOCTL_APP_GET_DELAY:\r
+                       if (copy_to_user(argp, &flag, sizeof(flag))) {\r
+                               return -EFAULT;\r
+                       }\r
+                       break;\r
+               default:\r
+                       break;\r
+       }\r
+\r
+       return result;\r
+}\r
+\r
+static int compass_dev_open(struct inode *inode, struct file *file)\r
+{\r
+#ifdef SENSOR_DEBUG_TYPE\r
+       struct sensor_private_data* sensor = \r
+               (struct sensor_private_data *)i2c_get_clientdata(this_client); \r
+#endif\r
+       int result = 0;\r
+       DBG("%s\n",__func__);\r
+\r
+       return result;\r
+}\r
+\r
+\r
+static int compass_dev_release(struct inode *inode, struct file *file)\r
+{\r
+#ifdef SENSOR_DEBUG_TYPE\r
+       struct sensor_private_data* sensor = \r
+               (struct sensor_private_data *)i2c_get_clientdata(this_client); \r
+#endif\r
+       int result = 0; \r
+       DBG("%s\n",__func__);\r
+\r
+       return result;\r
+}\r
+\r
+static int compass_akm_set_mode(struct i2c_client *client, char mode)\r
+{\r
+       struct sensor_private_data* sensor = (struct sensor_private_data *)i2c_get_clientdata(this_client); \r
+       int result = 0; \r
+\r
+       switch(mode)\r
+       {\r
+               case AK8975_MODE_SNG_MEASURE:\r
+               case AK8975_MODE_SELF_TEST:     \r
+               case AK8975_MODE_FUSE_ACCESS:                   \r
+                       if(sensor->status_cur == SENSOR_OFF)\r
+                       {\r
+                               if(sensor->pdata->irq_enable)\r
+                               {\r
+                                       //DBG("%s:enable irq=%d\n",__func__,client->irq);\r
+                                       //enable_irq(client->irq);\r
+                               }       \r
+                               else\r
+                               {\r
+                                       schedule_delayed_work(&sensor->delaywork, msecs_to_jiffies(sensor->pdata->poll_delay_ms));\r
+                               }\r
+                               \r
+                               sensor->status_cur = SENSOR_ON;\r
+                       }\r
+\r
+                       break;\r
+\r
+               case AK8975_MODE_POWERDOWN:     \r
+                       if(sensor->status_cur == SENSOR_ON)\r
+                       {\r
+                               if(sensor->pdata->irq_enable)\r
+                               {       \r
+                                       //DBG("%s:disable irq=%d\n",__func__,client->irq);\r
+                                       //disable_irq_nosync(client->irq);//disable irq\r
+                               }\r
+                               else\r
+                               cancel_delayed_work_sync(&sensor->delaywork);   \r
+\r
+                               sensor->status_cur = SENSOR_OFF;\r
+                       }\r
+                       break;\r
+\r
+       }\r
+       \r
+       switch(mode)\r
+       {\r
+               case AK8975_MODE_SNG_MEASURE:           \r
+                       result = sensor_write_reg(client, sensor->ops->ctrl_reg, AK8975_MODE_SNG_MEASURE);\r
+                       if(result)\r
+                       printk("%s:i2c error,mode=%d\n",__func__,mode);                         \r
+                       break;\r
+               case AK8975_MODE_SELF_TEST:                     \r
+                       result = sensor_write_reg(client, sensor->ops->ctrl_reg, AK8975_MODE_SELF_TEST);\r
+                       if(result)\r
+                       printk("%s:i2c error,mode=%d\n",__func__,mode);\r
+                       break;\r
+               case AK8975_MODE_FUSE_ACCESS:\r
+                       result = sensor_write_reg(client, sensor->ops->ctrl_reg, AK8975_MODE_FUSE_ACCESS);\r
+                       if(result)\r
+                       printk("%s:i2c error,mode=%d\n",__func__,mode);\r
+                       break;\r
+               case AK8975_MODE_POWERDOWN:\r
+                       /* Set powerdown mode */\r
+                       result = sensor_write_reg(client, sensor->ops->ctrl_reg, AK8975_MODE_POWERDOWN);\r
+                       if(result)\r
+                       printk("%s:i2c error,mode=%d\n",__func__,mode);\r
+                       udelay(100);\r
+                       break;\r
+               default:\r
+                       printk("%s: Unknown mode(%d)", __func__, mode);\r
+                       result = -EINVAL;\r
+                       break;\r
+       }\r
+       DBG("%s:mode=%d\n",__func__,mode);\r
+       return result;\r
+\r
+}\r
+\r
+\r
+static int compass_akm_get_openstatus(void)\r
+{\r
+       wait_event_interruptible(open_wq, (atomic_read(&open_flag) != 0));\r
+       return atomic_read(&open_flag);\r
+}\r
+\r
+static int compass_akm_get_closestatus(void)\r
+{\r
+       wait_event_interruptible(open_wq, (atomic_read(&open_flag) <= 0));\r
+       return atomic_read(&open_flag);\r
+}\r
+\r
+\r
+/* ioctl - I/O control */\r
+static long compass_dev_ioctl(struct file *file,\r
+                         unsigned int cmd, unsigned long arg)\r
+{\r
+    struct sensor_private_data* sensor = (struct sensor_private_data *)i2c_get_clientdata(this_client);\r
+       struct i2c_client *client = this_client;\r
+       void __user *argp = (void __user *)arg;\r
+       int result = 0;\r
+       struct akm8975_platform_data compass;\r
+               \r
+       /* NOTE: In this function the size of "char" should be 1-byte. */\r
+       char compass_data[SENSOR_DATA_SIZE];/* for GETDATA */\r
+       char rwbuf[RWBUF_SIZE];         /* for READ/WRITE */\r
+       char mode;                                      /* for SET_MODE*/\r
+       short value[12];                        /* for SET_YPR */\r
+       short delay;                            /* for GET_DELAY */\r
+       int status;                                     /* for OPEN/CLOSE_STATUS */\r
+       int ret = -1;                           /* Return value. */\r
+       \r
+       switch (cmd) {\r
+               case ECS_IOCTL_WRITE:\r
+               case ECS_IOCTL_READ:\r
+                       if (argp == NULL) {\r
+                               return -EINVAL;\r
+                       }\r
+                       if (copy_from_user(&rwbuf, argp, sizeof(rwbuf))) {\r
+                               return -EFAULT;\r
+                       }\r
+                       break;\r
+               case ECS_IOCTL_SET_MODE:\r
+                       if (argp == NULL) {\r
+                               return -EINVAL;\r
+                       }\r
+                       if (copy_from_user(&mode, argp, sizeof(mode))) {\r
+                               return -EFAULT;\r
+                       }\r
+                       break;\r
+               case ECS_IOCTL_SET_YPR:\r
+                       if (argp == NULL) {\r
+                               return -EINVAL;\r
+                       }\r
+                       if (copy_from_user(&value, argp, sizeof(value))) {\r
+                               return -EFAULT;\r
+                       }\r
+                       break;\r
+               default:\r
+                       break;\r
+       }\r
+       \r
+       switch (cmd) {\r
+               case ECS_IOCTL_WRITE:\r
+                       DBG("%s:ECS_IOCTL_WRITE start\n",__func__);\r
+                       mutex_lock(&sensor->operation_mutex);\r
+                       if ((rwbuf[0] < 2) || (rwbuf[0] > (RWBUF_SIZE-1))) {                    \r
+                               mutex_unlock(&sensor->operation_mutex);\r
+                               return -EINVAL;\r
+                       }\r
+                       ret = sensor_tx_data(client, &rwbuf[1], rwbuf[0]);\r
+                       if (ret < 0) {  \r
+                               mutex_unlock(&sensor->operation_mutex);         \r
+                               printk("%s:fait to tx data\n",__func__);\r
+                               return ret;\r
+                       }                       \r
+                       mutex_unlock(&sensor->operation_mutex);\r
+                       break;\r
+               case ECS_IOCTL_READ:                            \r
+                       DBG("%s:ECS_IOCTL_READ start\n",__func__);\r
+                       mutex_lock(&sensor->operation_mutex);\r
+                       if ((rwbuf[0] < 1) || (rwbuf[0] > (RWBUF_SIZE-1))) {            \r
+                               mutex_unlock(&sensor->operation_mutex);                 \r
+                               printk("%s:data is error\n",__func__);\r
+                               return -EINVAL;\r
+                       }\r
+                       ret = sensor_rx_data(client, &rwbuf[1], rwbuf[0]);\r
+                       if (ret < 0) {  \r
+                               mutex_unlock(&sensor->operation_mutex);         \r
+                               printk("%s:fait to rx data\n",__func__);\r
+                               return ret;\r
+                       }               \r
+                       mutex_unlock(&sensor->operation_mutex);\r
+                       break;\r
+               case ECS_IOCTL_SET_MODE:                \r
+                       DBG("%s:ECS_IOCTL_SET_MODE start\n",__func__);          \r
+                       mutex_lock(&sensor->operation_mutex);\r
+                       ret = compass_akm_set_mode(client, mode);\r
+                       if (ret < 0) {\r
+                               printk("%s:fait to set mode\n",__func__);               \r
+                               mutex_unlock(&sensor->operation_mutex);\r
+                               return ret;\r
+                       }               \r
+                       mutex_unlock(&sensor->operation_mutex);\r
+                       break;\r
+               case ECS_IOCTL_GETDATA:         \r
+                       DBG("%s:ECS_IOCTL_GETDATA start\n",__func__);\r
+                       mutex_lock(&sensor->data_mutex);        \r
+                       memcpy(compass_data, sensor->sensor_data, SENSOR_DATA_SIZE);    //get data from buffer\r
+                       mutex_unlock(&sensor->data_mutex);\r
+                       break;\r
+               case ECS_IOCTL_SET_YPR:                 \r
+                       DBG("%s:ECS_IOCTL_SET_YPR start\n",__func__);\r
+                       mutex_lock(&sensor->data_mutex);\r
+                       compass_set_YPR(value);         \r
+                       mutex_unlock(&sensor->data_mutex);\r
+                       break;\r
+               case ECS_IOCTL_GET_OPEN_STATUS:\r
+                       status = compass_akm_get_openstatus();  \r
+                       DBG("%s:openstatus=%d\n",__func__,status);\r
+                       break;\r
+               case ECS_IOCTL_GET_CLOSE_STATUS:
+                       status = compass_akm_get_closestatus(); \r
+                       DBG("%s:closestatus=%d\n",__func__,status);\r
+                       break;\r
+               case ECS_IOCTL_GET_DELAY:\r
+                       delay = akmd_delay;\r
+                       break;\r
+               case ECS_IOCTL_GET_PLATFORM_DATA:                       \r
+                       DBG("%s:ECS_IOCTL_GET_PLATFORM_DATA start\n",__func__);\r
+                       memcpy(compass.m_layout, sensor->pdata->m_layout, sizeof(sensor->pdata->m_layout));\r
+                       memcpy(compass.project_name, sensor->pdata->project_name, sizeof(sensor->pdata->project_name));\r
+                       ret = copy_to_user(argp, &compass, sizeof(compass));\r
+                       if(ret < 0)\r
+                       {\r
+                               printk("%s:error,ret=%d\n",__FUNCTION__, ret);\r
+                               return ret;\r
+                       }\r
+                       break;\r
+                       \r
+               default:\r
+                       return -ENOTTY;\r
+       }\r
+       \r
+       switch (cmd) {\r
+               case ECS_IOCTL_READ:\r
+                       if (copy_to_user(argp, &rwbuf, rwbuf[0]+1)) {\r
+                               return -EFAULT;\r
+                       }\r
+                       break;\r
+               case ECS_IOCTL_GETDATA:\r
+                       if (copy_to_user(argp, &compass_data, sizeof(compass_data))) {\r
+                               return -EFAULT;\r
+                       }\r
+                       break;\r
+               case ECS_IOCTL_GET_OPEN_STATUS:\r
+               case ECS_IOCTL_GET_CLOSE_STATUS:\r
+                       if (copy_to_user(argp, &status, sizeof(status))) {\r
+                               return -EFAULT;\r
+                       }\r
+                       break;\r
+               case ECS_IOCTL_GET_DELAY:\r
+                       if (copy_to_user(argp, &delay, sizeof(delay))) {\r
+                               return -EFAULT;\r
+                       }\r
+                       break;\r
+               default:\r
+                       break;\r
+       }\r
+\r
+       return result;\r
+}\r
+\r
+\r
+static struct file_operations compass_aot_fops =\r
+{\r
+       .owner = THIS_MODULE,\r
+       .unlocked_ioctl = compass_aot_ioctl,\r
+       .open = compass_aot_open,\r
+       .release = compass_aot_release,\r
+};\r
+\r
+\r
+\r
+static struct miscdevice compass_aot_device =\r
+{      \r
+       .minor = MISC_DYNAMIC_MINOR,\r
+       .name = "akm8975_aot",\r
+       .fops = &compass_aot_fops,\r
+};\r
+\r
+\r
+static struct file_operations compass_dev_fops =\r
+{\r
+       .owner = THIS_MODULE,\r
+       .open = compass_dev_open,\r
+       .release = compass_dev_release, \r
+       .unlocked_ioctl = compass_dev_ioctl,\r
+};\r
+\r
+\r
+static struct miscdevice compass_dev_device =\r
+{      \r
+       .minor = MISC_DYNAMIC_MINOR,\r
+       .name = "akm8975_dev",\r
+       .fops = &compass_dev_fops,\r
+};\r
+\r
+struct sensor_operate akm8975_ops = {\r
+       .name                           = "akm8975",\r
+       .type                           = SENSOR_TYPE_COMPASS,  //it is important\r
+       .id_i2c                         = COMPASS_ID_AK8975,\r
+       .read_reg                       = AK8975_REG_ST1,       //read data\r
+       .read_len                       = SENSOR_DATA_SIZE,     //data length\r
+       .id_reg                         = AK8975_REG_WIA,       //read id\r
+       .id_data                        = AK8975_DEVICE_ID,\r
+       .precision                      = 8,                    //12 bits\r
+       .ctrl_reg                       = AK8975_REG_CNTL,      //enable or disable \r
+       .int_status_reg                 = SENSOR_UNKNOW_DATA,   //not exist\r
+       .range                          = {-0xffff,0xffff},\r
+       .trig                           = IRQF_TRIGGER_RISING,  //if LEVEL interrupt then IRQF_ONESHOT\r
+       .active                         = sensor_active,        \r
+       .init                           = sensor_init,\r
+       .report                         = sensor_report_value,  \r
+       .misc_dev                       = &compass_dev_device,  //private misc support\r
+};\r
+\r
+/****************operate according to sensor chip:end************/\r
+\r
+//function name should not be changed\r
+struct sensor_operate *compass_get_ops(void)\r
+{\r
+       return &akm8975_ops;\r
+}\r
+\r
+EXPORT_SYMBOL(compass_get_ops);\r
+\r
+\r
+static int __init compass_init(void)\r
+{\r
+       struct sensor_operate *ops = compass_get_ops();\r
+       int result = 0;\r
+       int type = ops->type;\r
+       result = sensor_register_slave(type, NULL, NULL, compass_get_ops);\r
+\r
+       result = misc_register(&compass_aot_device);\r
+       if (result < 0) {\r
+               printk("%s:fail to register misc device %s\n", __func__, compass_aot_device.name);\r
+               goto error;\r
+       }\r
+\r
+       /* As default, report all information */\r
+       atomic_set(&m_flag, 1);\r
+       atomic_set(&a_flag, 1);\r
+       atomic_set(&mv_flag, 1);                        \r
+       atomic_set(&open_flag, 0);              \r
+       init_waitqueue_head(&open_wq);\r
+                       \r
+       printk("%s\n",__func__);\r
+error:\r
+       return result;\r
+}\r
+\r
+static void __exit compass_exit(void)\r
+{\r
+       struct sensor_operate *ops = compass_get_ops();\r
+       int type = ops->type;\r
+       sensor_unregister_slave(type, NULL, NULL, compass_get_ops);\r
+}\r
+\r
+\r
+module_init(compass_init);\r
+module_exit(compass_exit);\r
+\r
+\r
diff --git a/drivers/input/sensors/gyro/Kconfig b/drivers/input/sensors/gyro/Kconfig
new file mode 100755 (executable)
index 0000000..ab5233f
--- /dev/null
@@ -0,0 +1,19 @@
+#
+# gyroscope drivers configuration
+#
+
+menuconfig GYROSCOPE_DEVICE
+       bool "gyroscope device support"
+       default n       
+
+if GYROSCOPE_DEVICE
+
+config GYRO_L3G4200D
+  bool "gyroscope l3g4200d"
+       default n
+
+config GYRO_K3G
+  bool "gyroscope k3g"
+       default n
+
+endif
diff --git a/drivers/input/sensors/gyro/Makefile b/drivers/input/sensors/gyro/Makefile
new file mode 100755 (executable)
index 0000000..c531f62
--- /dev/null
@@ -0,0 +1,4 @@
+# gyroscope drivers
+
+obj-$(CONFIG_GYRO_SENSOR_K3G)  += k3g.o
+obj-$(CONFIG_GYRO_L3G4200D)    += l3g4200d.o
\ No newline at end of file
diff --git a/drivers/input/sensors/gyro/l3g4200d.c b/drivers/input/sensors/gyro/l3g4200d.c
new file mode 100755 (executable)
index 0000000..761ccd2
--- /dev/null
@@ -0,0 +1,267 @@
+/* drivers/input/sensors/access/kxtik.c\r
+ *\r
+ * Copyright (C) 2012-2015 ROCKCHIP.\r
+ * Author: luowei <lw@rock-chips.com>\r
+ *\r
+ * This software is licensed under the terms of the GNU General Public\r
+ * License version 2, as published by the Free Software Foundation, and\r
+ * may be copied, distributed, and modified under those terms.\r
+ *\r
+ * This program is distributed in the hope that it will be useful,\r
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+ * GNU General Public License for more details.\r
+ *\r
+ */\r
+#include <linux/interrupt.h>\r
+#include <linux/i2c.h>\r
+#include <linux/slab.h>\r
+#include <linux/irq.h>\r
+#include <linux/miscdevice.h>\r
+#include <linux/gpio.h>\r
+#include <asm/uaccess.h>\r
+#include <asm/atomic.h>\r
+#include <linux/delay.h>\r
+#include <linux/input.h>\r
+#include <linux/workqueue.h>\r
+#include <linux/freezer.h>\r
+#include <mach/gpio.h>\r
+#include <mach/board.h> \r
+#ifdef CONFIG_HAS_EARLYSUSPEND\r
+#include <linux/earlysuspend.h>\r
+#endif\r
+#include <linux/l3g4200d.h>\r
+#include <linux/sensor-dev.h>\r
+\r
+#if 0\r
+#define SENSOR_DEBUG_TYPE SENSOR_TYPE_GYROSCOPE\r
+#define DBG(x...) if(sensor->pdata->type == SENSOR_DEBUG_TYPE) printk(x)\r
+#else\r
+#define DBG(x...)\r
+#endif\r
+\r
+#define L3G4200D_ENABLE                        0x08\r
+\r
+/****************operate according to sensor chip:start************/\r
+\r
+static int sensor_active(struct i2c_client *client, int enable, int rate)\r
+{\r
+       struct sensor_private_data *sensor =\r
+           (struct sensor_private_data *) i2c_get_clientdata(client);  \r
+       int result = 0;\r
+       int status = 0;\r
+               \r
+       sensor->ops->ctrl_data = sensor_read_reg(client, sensor->ops->ctrl_reg);\r
+\r
+       //register setting according to chip datasheet          \r
+       if(enable)\r
+       {       \r
+               status = L3G4200D_ENABLE;       //l3g4200d      \r
+               sensor->ops->ctrl_data |= status;       \r
+       }\r
+       else\r
+       {\r
+               status = ~L3G4200D_ENABLE;      //l3g4200d\r
+               sensor->ops->ctrl_data &= status;\r
+       }\r
+\r
+       DBG("%s:reg=0x%x,reg_ctrl=0x%x,enable=%d\n",__func__,sensor->ops->ctrl_reg, sensor->ops->ctrl_data, enable);\r
+       result = sensor_write_reg(client, sensor->ops->ctrl_reg, sensor->ops->ctrl_data);\r
+       if(result)\r
+               printk("%s:fail to active sensor\n",__func__);\r
+\r
+       return result;\r
+\r
+}\r
+\r
+static int sensor_init(struct i2c_client *client)\r
+{      \r
+       struct sensor_private_data *sensor =\r
+           (struct sensor_private_data *) i2c_get_clientdata(client);  \r
+       int result = 0; \r
+       unsigned char buf[5];           \r
+       unsigned char data = 0;\r
+       int i = 0;\r
+       \r
+       result = sensor->ops->active(client,0,0);\r
+       if(result)\r
+       {\r
+               printk("%s:line=%d,error\n",__func__,__LINE__);\r
+               return result;\r
+       }\r
+       \r
+       sensor->status_cur = SENSOR_OFF;\r
+       \r
+       buf[0] = 0x07;  //27\r
+       buf[1] = 0x00;  \r
+       buf[2] = 0x00;  \r
+       buf[3] = 0x20;  //0x00\r
+       buf[4] = 0x00;  \r
+       for(i=0; i<5; i++)\r
+       {\r
+               result = sensor_write_reg(client, sensor->ops->ctrl_reg+i, buf[i]);\r
+               if(result)\r
+               {\r
+                       printk("%s:line=%d,error\n",__func__,__LINE__);\r
+                       return result;\r
+               }\r
+       }\r
+       \r
+       result = sensor_read_reg(client, sensor->ops->ctrl_reg);\r
+       if (result >= 0)\r
+               data = result & 0x000F;\r
+
+       sensor->ops->ctrl_data = data + ODR100_BW12_5;  \r
+       result = sensor_write_reg(client, sensor->ops->ctrl_reg, sensor->ops->ctrl_data);\r
+       if(result)\r
+       {\r
+               printk("%s:line=%d,error\n",__func__,__LINE__);\r
+               return result;\r
+       }\r
+       \r
+       return result;\r
+}\r
+\r
+\r
+static int gyro_report_value(struct i2c_client *client, struct sensor_axis *axis)\r
+{\r
+       struct sensor_private_data *sensor =\r
+               (struct sensor_private_data *) i2c_get_clientdata(client);      \r
+\r
+       /* Report GYRO  information */\r
+       input_report_rel(sensor->input_dev, ABS_RX, axis->x);\r
+       input_report_rel(sensor->input_dev, ABS_RY, axis->y);\r
+       input_report_rel(sensor->input_dev, ABS_RZ, axis->z);\r
+       input_sync(sensor->input_dev);\r
+       DBG("gyro x==%d  y==%d z==%d\n",axis->x,axis->y,axis->z);\r
+\r
+       return 0;\r
+}\r
+\r
+static int sensor_report_value(struct i2c_client *client)\r
+{\r
+       struct sensor_private_data *sensor =\r
+               (struct sensor_private_data *) i2c_get_clientdata(client);      \r
+       struct sensor_platform_data *pdata = sensor->pdata;\r
+       int ret = 0;\r
+       int x = 0, y = 0, z = 0;\r
+       struct sensor_axis axis;\r
+       char buffer[6] = {0};   \r
+       int i = 0;\r
+       \r
+       if(sensor->ops->read_len < 6)   //sensor->ops->read_len = 6\r
+       {\r
+               printk("%s:lenth is error,len=%d\n",__func__,sensor->ops->read_len);\r
+               return -1;\r
+       }\r
+       \r
+       memset(buffer, 0, 6);\r
+#if 0  \r
+       /* Data bytes from hardware xL, xH, yL, yH, zL, zH */   \r
+       do {\r
+               buffer[0] = sensor->ops->read_reg;\r
+               ret = sensor_rx_data(client, buffer, sensor->ops->read_len);\r
+               if (ret < 0)\r
+               return ret;\r
+       } while (0);\r
+#else\r
+\r
+       for(i=0; i<6; i++)\r
+       {
+               //buffer[i] = sensor->ops->read_reg + i;        \r
+               buffer[i] = sensor_read_reg(client, sensor->ops->read_reg + i);\r
+       }\r
+#endif\r
+       x = (short) (((buffer[1]) << 8) | buffer[0]);\r
+       y = (short) (((buffer[3]) << 8) | buffer[2]);\r
+       z = (short) (((buffer[5]) << 8) | buffer[4]);\r
+
+       DBG("%s: x=%d  y=%d z=%d \n",__func__, x,y,z);
+       if(pdata && pdata->orientation)
+       {
+               axis.x = (pdata->orientation[0])*x + (pdata->orientation[1])*y + (pdata->orientation[2])*z;
+               axis.y = (pdata->orientation[3])*x + (pdata->orientation[4])*y + (pdata->orientation[5])*z;     
+               axis.z = (pdata->orientation[6])*x + (pdata->orientation[7])*y + (pdata->orientation[8])*z;
+       }
+       else
+       {
+               axis.x = x;     
+               axis.y = y;
+               axis.z = z;     
+       }
+
+       //filter gyro data
+       if((abs(axis.x) > pdata->x_min)||(abs(axis.y) > pdata->y_min)||(abs(axis.z) > pdata->z_min))\r
+       {       \r
+               gyro_report_value(client, &axis);       \r
+\r
+                /* »¥³âµØ»º´æÊý¾Ý. */\r
+               mutex_lock(&(sensor->data_mutex) );\r
+               sensor->axis = axis;\r
+               mutex_unlock(&(sensor->data_mutex) );\r
+       }       \r
+\r
+       if((sensor->pdata->irq_enable)&& (sensor->ops->int_status_reg >= 0))    //read sensor intterupt status register\r
+       {\r
+               \r
+               ret= sensor_read_reg(client, sensor->ops->int_status_reg);\r
+               if(ret)\r
+               {\r
+                       printk("%s:fail to clear sensor int status,ret=0x%x\n",__func__,ret);\r
+               }\r
+       }\r
+       \r
+       return ret;\r
+}\r
+\r
+\r
+struct sensor_operate gyro_ops = {\r
+       .name                           = "l3g4200d",\r
+       .type                           = SENSOR_TYPE_GYROSCOPE,//sensor type and it should be correct\r
+       .id_i2c                         = GYRO_ID_L3G4200D,             //i2c id number\r
+       .read_reg                       = GYRO_DATA_REG,                //read data\r
+       .read_len                       = 6,                            //data length\r
+       .id_reg                         = GYRO_WHO_AM_I,                //read device id from this register\r
+       .id_data                        = GYRO_DEVID_L3G4200D,          //device id\r
+       .precision                      = 8,                            //8 bits\r
+       .ctrl_reg                       = GYRO_CTRL_REG1,               //enable or disable \r
+       .int_status_reg                 = GYRO_INT_SRC,                 //intterupt status register,if no exist then -1\r
+       .range                          = {-32768,32768},               //range\r
+       .trig                           = IRQF_TRIGGER_LOW|IRQF_ONESHOT,                \r
+       .active                         = sensor_active,        \r
+       .init                           = sensor_init,\r
+       .report                         = sensor_report_value,\r
+};\r
+\r
+/****************operate according to sensor chip:end************/\r
+\r
+//function name should not be changed\r
+struct sensor_operate *gyro_get_ops(void)\r
+{\r
+       return &gyro_ops;\r
+}\r
+\r
+EXPORT_SYMBOL(gyro_get_ops);\r
+\r
+static int __init gyro_init(void)\r
+{\r
+       struct sensor_operate *ops = gyro_get_ops();\r
+       int result = 0;\r
+       int type = ops->type;\r
+       result = sensor_register_slave(type, NULL, NULL, gyro_get_ops);\r
+       printk("%s\n",__func__);\r
+       return result;\r
+}\r
+\r
+static void __exit gyro_exit(void)\r
+{\r
+       struct sensor_operate *ops = gyro_get_ops();\r
+       int type = ops->type;\r
+       sensor_unregister_slave(type, NULL, NULL, gyro_get_ops);\r
+}\r
+\r
+\r
+module_init(gyro_init);\r
+module_exit(gyro_exit);\r
+\r
+\r
diff --git a/drivers/input/sensors/lsensor/Kconfig b/drivers/input/sensors/lsensor/Kconfig
new file mode 100755 (executable)
index 0000000..5cd3807
--- /dev/null
@@ -0,0 +1,22 @@
+#
+# light and position sensor drivers configuration
+#
+
+menuconfig LIGHT_DEVICE
+       bool "light sensor device support"
+       default n       
+
+if LIGHT_DEVICE
+config LS_CM3217
+  bool "light sensor cm3217"
+       default n
+config LS_AL3006
+  bool "light sensor al3006"
+       default n
+
+config LS_STK3171
+  bool "light sensor stk3171"
+       default n         
+endif
+
diff --git a/drivers/input/sensors/lsensor/Makefile b/drivers/input/sensors/lsensor/Makefile
new file mode 100755 (executable)
index 0000000..98836f4
--- /dev/null
@@ -0,0 +1,5 @@
+# gsensor drivers
+
+obj-$(CONFIG_LS_CM3217)                += cm3217.o
+obj-$(CONFIG_LS_AL3006)                += ls_al3006.o
+obj-$(CONFIG_LS_STK3171)               += ls_stk3171.o
\ No newline at end of file
diff --git a/drivers/input/sensors/lsensor/cm3217.c b/drivers/input/sensors/lsensor/cm3217.c
new file mode 100755 (executable)
index 0000000..b51f271
--- /dev/null
@@ -0,0 +1,238 @@
+/* drivers/input/sensors/access/kxtik.c\r
+ *\r
+ * Copyright (C) 2012-2015 ROCKCHIP.\r
+ * Author: luowei <lw@rock-chips.com>\r
+ *\r
+ * This software is licensed under the terms of the GNU General Public\r
+ * License version 2, as published by the Free Software Foundation, and\r
+ * may be copied, distributed, and modified under those terms.\r
+ *\r
+ * This program is distributed in the hope that it will be useful,\r
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+ * GNU General Public License for more details.\r
+ *\r
+ */\r
+#include <linux/interrupt.h>\r
+#include <linux/i2c.h>\r
+#include <linux/slab.h>\r
+#include <linux/irq.h>\r
+#include <linux/miscdevice.h>\r
+#include <linux/gpio.h>\r
+#include <asm/uaccess.h>\r
+#include <asm/atomic.h>\r
+#include <linux/delay.h>\r
+#include <linux/input.h>\r
+#include <linux/workqueue.h>\r
+#include <linux/freezer.h>\r
+#include <mach/gpio.h>\r
+#include <mach/board.h> \r
+#ifdef CONFIG_HAS_EARLYSUSPEND\r
+#include <linux/earlysuspend.h>\r
+#endif\r
+#include <linux/sensor-dev.h>\r
+\r
+#if 0\r
+#define SENSOR_DEBUG_TYPE SENSOR_TYPE_LIGHT\r
+#define DBG(x...) if(sensor->pdata->type == SENSOR_DEBUG_TYPE) printk(x)\r
+#else\r
+#define DBG(x...)\r
+#endif\r
+\r
+#define CM3217_ADDR_COM1       0x10\r
+#define CM3217_ADDR_COM2       0x11\r
+#define CM3217_ADDR_DATA_MSB   0x10\r
+#define CM3217_ADDR_DATA_LSB   0x11\r
+\r
+#define CM3217_COM1_VALUE      0xA7    // (GAIN1:GAIN0)=10, (IT_T1:IT_TO)=01,WMD=1,SD=1,\r
+#define CM3217_COM2_VALUE      0xA0    //100ms\r
+\r
+#define CM3217_CLOSE   0x01\r
+\r
+\r
+\r
+/****************operate according to sensor chip:start************/\r
+\r
+static int sensor_active(struct i2c_client *client, int enable, int rate)\r
+{\r
+       struct sensor_private_data *sensor =\r
+           (struct sensor_private_data *) i2c_get_clientdata(client);  \r
+       int result = 0;\r
+       int status = 0;\r
+       \r
+       sensor->client->addr = sensor->ops->ctrl_reg;   \r
+       sensor->ops->ctrl_data = sensor_read_reg_normal(client);\r
+       \r
+       //register setting according to chip datasheet          \r
+       if(!enable)\r
+       {       \r
+               status = CM3217_CLOSE;  //cm3217        \r
+               sensor->ops->ctrl_data |= status;       \r
+       }\r
+       else\r
+       {\r
+               status = ~CM3217_CLOSE; //cm3217\r
+               sensor->ops->ctrl_data &= status;\r
+       }\r
+\r
+       DBG("%s:reg=0x%x,reg_ctrl=0x%x,enable=%d\n",__func__,sensor->ops->ctrl_reg, sensor->ops->ctrl_data, enable);\r
+       result = sensor_write_reg_normal(client, sensor->ops->ctrl_data);\r
+       if(result)\r
+               printk("%s:fail to active sensor\n",__func__);\r
+       \r
+       return result;\r
+\r
+}\r
+\r
+\r
+static int sensor_init(struct i2c_client *client)\r
+{      \r
+       struct sensor_private_data *sensor =\r
+           (struct sensor_private_data *) i2c_get_clientdata(client);  \r
+       int result = 0;\r
+       \r
+       result = sensor->ops->active(client,0,0);\r
+       if(result)\r
+       {\r
+               printk("%s:line=%d,error\n",__func__,__LINE__);\r
+               return result;\r
+       }\r
+       \r
+       sensor->status_cur = SENSOR_OFF;\r
+       \r
+       sensor->client->addr = sensor->ops->ctrl_reg;           \r
+       sensor->ops->ctrl_data = CM3217_COM1_VALUE;     \r
+       result = sensor_write_reg_normal(client, sensor->ops->ctrl_data);\r
+       if(result)\r
+       {\r
+               printk("%s:line=%d,error\n",__func__,__LINE__);\r
+               return result;\r
+       }\r
+       \r
+       sensor->client->addr = CM3217_ADDR_COM2;        \r
+       result = sensor_write_reg_normal(client, CM3217_COM2_VALUE);\r
+       if(result)\r
+       {\r
+               printk("%s:line=%d,error\n",__func__,__LINE__);\r
+               return result;\r
+       }\r
+       \r
+       return result;\r
+}\r
+\r
+\r
+static void light_report_value(struct input_dev *input, int data)\r
+{\r
+       unsigned char index = 0;\r
+       if(data <= 10){\r
+               index = 0;goto report;\r
+       }\r
+       else if(data <= 160){\r
+               index = 1;goto report;\r
+       }\r
+       else if(data <= 225){\r
+               index = 2;goto report;\r
+       }\r
+       else if(data <= 320){\r
+               index = 3;goto report;\r
+       }\r
+       else if(data <= 640){\r
+               index = 4;goto report;\r
+       }\r
+       else if(data <= 1280){\r
+               index = 5;goto report;\r
+       }\r
+       else if(data <= 2600){\r
+               index = 6;goto report;\r
+       }\r
+       else{\r
+               index = 7;goto report;\r
+       }\r
+\r
+report:\r
+       DBG("cm3217 report data=%d,index = %d\n",data,index);\r
+       input_report_abs(input, ABS_MISC, index);\r
+       input_sync(input);\r
+}\r
+\r
+\r
+static int sensor_report_value(struct i2c_client *client)\r
+{\r
+       struct sensor_private_data *sensor =\r
+           (struct sensor_private_data *) i2c_get_clientdata(client);  \r
+       int result = 0;\r
+       char msb = 0, lsb = 0;\r
+       \r
+       sensor->client->addr = CM3217_ADDR_DATA_LSB;\r
+       sensor_rx_data_normal(sensor->client, &lsb, 1);\r
+       sensor->client->addr = CM3217_ADDR_DATA_MSB;\r
+       sensor_rx_data_normal(sensor->client, &msb, 1);\r
+       result = ((msb << 8) | lsb) & 0xffff;\r
+       \r
+       DBG("%s:result=%d\n",__func__,result);\r
+       light_report_value(sensor->input_dev, result);\r
+\r
+       if((sensor->pdata->irq_enable)&& (sensor->ops->int_status_reg >= 0))    //read sensor intterupt status register\r
+       {\r
+               \r
+               result= sensor_read_reg(client, sensor->ops->int_status_reg);\r
+               if(result)\r
+               {\r
+                       printk("%s:fail to clear sensor int status,ret=0x%x\n",__func__,result);\r
+               }\r
+       }\r
+       \r
+       return result;\r
+}\r
+\r
+\r
+struct sensor_operate light_ops = {\r
+       .name                           = "cm3217",\r
+       .type                           = SENSOR_TYPE_LIGHT,    //sensor type and it should be correct\r
+       .id_i2c                         = LIGHT_ID_CM3217,      //i2c id number\r
+       .read_reg                       = CM3217_ADDR_DATA_LSB, //read data\r
+       .read_len                       = 2,                    //data length\r
+       .id_reg                         = SENSOR_UNKNOW_DATA,   //read device id from this register\r
+       .id_data                        = SENSOR_UNKNOW_DATA,   //device id\r
+       .precision                      = 8,                    //8 bits\r
+       .ctrl_reg                       = CM3217_ADDR_COM1,     //enable or disable \r
+       .int_status_reg                 = SENSOR_UNKNOW_DATA,   //intterupt status register\r
+       .range                          = {0,10},               //range\r
+       .trig                           = SENSOR_UNKNOW_DATA,           \r
+       .active                         = sensor_active,        \r
+       .init                           = sensor_init,\r
+       .report                         = sensor_report_value,\r
+};\r
+\r
+/****************operate according to sensor chip:end************/\r
+\r
+//function name should not be changed\r
+struct sensor_operate *light_get_ops(void)\r
+{\r
+       return &light_ops;\r
+}\r
+\r
+EXPORT_SYMBOL(light_get_ops);\r
+\r
+static int __init light_init(void)\r
+{\r
+       struct sensor_operate *ops = light_get_ops();\r
+       int result = 0;\r
+       int type = ops->type;\r
+       result = sensor_register_slave(type, NULL, NULL, light_get_ops);\r
+       printk("%s\n",__func__);\r
+       return result;\r
+}\r
+\r
+static void __exit light_exit(void)\r
+{\r
+       struct sensor_operate *ops = light_get_ops();\r
+       int type = ops->type;\r
+       sensor_unregister_slave(type, NULL, NULL, light_get_ops);\r
+}\r
+\r
+\r
+module_init(light_init);\r
+module_exit(light_exit);\r
+\r
+\r
diff --git a/drivers/input/sensors/lsensor/ls_al3006.c b/drivers/input/sensors/lsensor/ls_al3006.c
new file mode 100755 (executable)
index 0000000..0700ff3
--- /dev/null
@@ -0,0 +1,299 @@
+/* drivers/input/sensors/access/kxtik.c\r
+ *\r
+ * Copyright (C) 2012-2015 ROCKCHIP.\r
+ * Author: luowei <lw@rock-chips.com>\r
+ *\r
+ * This software is licensed under the terms of the GNU General Public\r
+ * License version 2, as published by the Free Software Foundation, and\r
+ * may be copied, distributed, and modified under those terms.\r
+ *\r
+ * This program is distributed in the hope that it will be useful,\r
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+ * GNU General Public License for more details.\r
+ *\r
+ */\r
+#include <linux/interrupt.h>\r
+#include <linux/i2c.h>\r
+#include <linux/slab.h>\r
+#include <linux/irq.h>\r
+#include <linux/miscdevice.h>\r
+#include <linux/gpio.h>\r
+#include <asm/uaccess.h>\r
+#include <asm/atomic.h>\r
+#include <linux/delay.h>\r
+#include <linux/input.h>\r
+#include <linux/workqueue.h>\r
+#include <linux/freezer.h>\r
+#include <mach/gpio.h>\r
+#include <mach/board.h> \r
+#ifdef CONFIG_HAS_EARLYSUSPEND\r
+#include <linux/earlysuspend.h>\r
+#endif\r
+#include <linux/sensor-dev.h>\r
+\r
+#if 0\r
+#define SENSOR_DEBUG_TYPE SENSOR_TYPE_LIGHT\r
+#define DBG(x...) if(sensor->pdata->type == SENSOR_DEBUG_TYPE) printk(x)\r
+#else\r
+#define DBG(x...)\r
+#endif\r
+\r
+#define CONFIG_REG        (0x00)\r
+#define TIM_CTL_REG       (0x01)\r
+#define ALS_CTL_REG       (0x02)\r
+#define INT_STATUS_REG    (0x03)\r
+#define PS_CTL_REG        (0x04)\r
+#define PS_ALS_DATA_REG   (0x05)\r
+#define ALS_WINDOWS_REG   (0x08)\r
+\r
+//enable bit[ 0-1], in register CONFIG_REG\r
+#define ONLY_ALS_EN       (0x00)\r
+#define ONLY_PROX_EN      (0x01)\r
+#define ALL_PROX_ALS_EN   (0x02)\r
+#define ALL_IDLE          (0x03)\r
+\r
+#define POWER_MODE_MASK   (0x0C)\r
+#define POWER_UP_MODE     (0x00)\r
+#define POWER_DOWN_MODE   (0x08)\r
+#define POWER_RESET_MODE  (0x0C)\r
+\r
+static int sensor_power_updown(struct i2c_client *client, int on)\r
+{\r
+       int result = 0;\r
+       char value = 0;\r
+       int i = 0;\r
+       for(i=0; i<3; i++)\r
+       {\r
+               if(!on)\r
+               {\r
+                       result = sensor_write_reg(client, CONFIG_REG, POWER_DOWN_MODE);\r
+                       if(result)\r
+                               return result;\r
+               }\r
+               else\r
+               {\r
+                       value = sensor_read_reg(client, CONFIG_REG);\r
+                       value &= ~POWER_MODE_MASK;\r
+                       value |= POWER_UP_MODE;\r
+                       result = sensor_write_reg(client, CONFIG_REG, value);\r
+                       if(result)\r
+                               return result;\r
+               }\r
+               \r
+               if(!result)\r
+               break;\r
+       }\r
+\r
+       if(i>1)\r
+       printk("%s:set %d times",__func__,i);\r
+       \r
+       return result;\r
+}\r
+\r
+/****************operate according to sensor chip:start************/\r
+\r
+static int sensor_active(struct i2c_client *client, int enable, int rate)\r
+{\r
+       struct sensor_private_data *sensor =\r
+           (struct sensor_private_data *) i2c_get_clientdata(client);  \r
+       int result = 0;\r
+       char value = 0;\r
+\r
+       sensor->ops->ctrl_data = sensor_read_reg(client, sensor->ops->ctrl_reg);\r
+       \r
+       //register setting according to chip datasheet          \r
+       if(enable)\r
+       {       \r
+               if( (sensor->ops->ctrl_data & 0x03) == ONLY_PROX_EN )\r
+               {\r
+                       value &= ~0x03;\r
+                       value |= ALL_PROX_ALS_EN;\r
+               }\r
+               else if((value & 0x03) == ALL_IDLE )\r
+               {\r
+                       value &= ~0x03;\r
+                       value |= ONLY_ALS_EN;\r
+               }\r
+\r
+               sensor_power_updown(client, 1);\r
+       }\r
+       else\r
+       {\r
+               if( (sensor->ops->ctrl_data & 0x03) == ONLY_ALS_EN )\r
+               {\r
+                       value &= ~0x03;\r
+                       value |= ALL_IDLE;\r
+               }\r
+               else if((sensor->ops->ctrl_data & 0x03) == ALL_PROX_ALS_EN )\r
+               {\r
+                       value &= ~0x03;\r
+                       value |= ONLY_PROX_EN;\r
+               }\r
+       \r
+       }\r
+       \r
+       sensor->ops->ctrl_data = value;\r
+       \r
+       DBG("%s:reg=0x%x,reg_ctrl=0x%x,enable=%d\n",__func__,sensor->ops->ctrl_reg, sensor->ops->ctrl_data, enable);\r
+       result = sensor_write_reg(client, sensor->ops->ctrl_reg, sensor->ops->ctrl_data);\r
+       if(result)\r
+               printk("%s:fail to active sensor\n",__func__);\r
+\r
+       return result;\r
+\r
+}\r
+\r
+\r
+static int sensor_init(struct i2c_client *client)\r
+{      \r
+       struct sensor_private_data *sensor =\r
+           (struct sensor_private_data *) i2c_get_clientdata(client);  \r
+       int result = 0;\r
+       char value = 0;\r
+\r
+       \r
+       sensor_power_updown(client, 0);\r
+       \r
+       result = sensor->ops->active(client,0,0);\r
+       if(result)\r
+       {\r
+               printk("%s:line=%d,error\n",__func__,__LINE__);\r
+               return result;\r
+       }\r
+       \r
+       sensor->status_cur = SENSOR_OFF;\r
+\r
+       value = 0x41;//The ADC effective resolution = 9;  Low lux threshold level = 1;\r
+       //value = 0x69; //The ADC effective resolution = 17;  Low lux threshold level = 9;
+       result = sensor_write_reg(client, ALS_CTL_REG, value);\r
+       if(result)\r
+       {\r
+               printk("%s:line=%d,error\n",__func__,__LINE__);\r
+               return result;\r
+       }\r
+
+       //value = 0x04;//0x01-0x0f; 17%->93.5% if value = 0x04,then Compensate Loss 52%
+       value = 0x02;//0x01-0x0f; 17%->93.5% if value = 0x02,then Compensate Loss 31%   \r
+       result = sensor_write_reg(client, ALS_WINDOWS_REG, value);\r
+       if(result)\r
+       {\r
+               printk("%s:line=%d,error\n",__func__,__LINE__);\r
+               return result;\r
+       }\r
+               \r
+       return result;\r
+}\r
+\r
+\r
+static int light_report_value(struct input_dev *input, int data)\r
+{\r
+       unsigned char index = 0;\r
+       if(data <= 0){\r
+               index = 0;goto report;\r
+       }\r
+       else if(data <= 2){\r
+               index = 1;goto report;\r
+       }\r
+       else if(data <= 4){\r
+               index = 2;goto report;\r
+       }\r
+       else if(data <= 8){\r
+               index = 3;goto report;\r
+       }\r
+       else if(data <= 14){\r
+               index = 4;goto report;\r
+       }\r
+       else if(data <= 20){\r
+               index = 5;goto report;\r
+       }\r
+       else if(data <= 26){\r
+               index = 6;goto report;\r
+       }\r
+       else{\r
+               index = 7;goto report;\r
+       }\r
+\r
+report:\r
+       input_report_abs(input, ABS_MISC, index);\r
+       input_sync(input);\r
+\r
+       return index;\r
+}\r
+\r
+\r
+static int sensor_report_value(struct i2c_client *client)\r
+{\r
+       struct sensor_private_data *sensor =\r
+           (struct sensor_private_data *) i2c_get_clientdata(client);  \r
+       int result = 0;\r
+       char value = 0;\r
+       char index = 0;\r
+       \r
+       if(sensor->pdata->irq_enable)\r
+       {\r
+               if(sensor->ops->int_status_reg)\r
+               {\r
+                       value = sensor_read_reg(client, sensor->ops->int_status_reg);\r
+               }\r
+               \r
+       }\r
+\r
+       value = sensor_read_reg(client, sensor->ops->read_reg);\r
+       index = light_report_value(sensor->input_dev, value&0x3f); // bit0-5  is ls data;\r
+       \r
+       DBG("%s:%s result=0x%x,index=%d\n",__func__,sensor->ops->name, value,index);\r
+       \r
+       return result;\r
+}\r
+\r
+struct sensor_operate light_ops = {\r
+       .name                           = "ls_al3006",\r
+       .type                           = SENSOR_TYPE_LIGHT,    //sensor type and it should be correct\r
+       .id_i2c                         = LIGHT_ID_AL3006,      //i2c id number\r
+       .read_reg                       = PS_ALS_DATA_REG,      //read data\r
+       .read_len                       = 1,                    //data length\r
+       .id_reg                         = SENSOR_UNKNOW_DATA,   //read device id from this register\r
+       .id_data                        = SENSOR_UNKNOW_DATA,   //device id\r
+       .precision                      = 8,                    //8 bits\r
+       .ctrl_reg                       = CONFIG_REG,           //enable or disable \r
+       .int_status_reg                 = INT_STATUS_REG,       //intterupt status register\r
+       .range                          = {0,10},               //range\r
+       .trig                           = IRQF_TRIGGER_LOW | IRQF_ONESHOT | IRQF_SHARED,                \r
+       .active                         = sensor_active,        \r
+       .init                           = sensor_init,\r
+       .report                         = sensor_report_value,\r
+};\r
+\r
+/****************operate according to sensor chip:end************/\r
+\r
+//function name should not be changed\r
+struct sensor_operate *light_get_ops(void)\r
+{\r
+       return &light_ops;\r
+}\r
+\r
+EXPORT_SYMBOL(light_get_ops);\r
+\r
+static int __init light_init(void)\r
+{\r
+       struct sensor_operate *ops = light_get_ops();\r
+       int result = 0;\r
+       int type = ops->type;\r
+       result = sensor_register_slave(type, NULL, NULL, light_get_ops);\r
+       printk("%s\n",__func__);\r
+       return result;\r
+}\r
+\r
+static void __exit light_exit(void)\r
+{\r
+       struct sensor_operate *ops = light_get_ops();\r
+       int type = ops->type;\r
+       sensor_unregister_slave(type, NULL, NULL, light_get_ops);\r
+}\r
+\r
+\r
+module_init(light_init);\r
+module_exit(light_exit);\r
+\r
+\r
diff --git a/drivers/input/sensors/lsensor/ls_stk3171.c b/drivers/input/sensors/lsensor/ls_stk3171.c
new file mode 100755 (executable)
index 0000000..307e148
--- /dev/null
@@ -0,0 +1,301 @@
+/* drivers/input/sensors/access/kxtik.c\r
+ *\r
+ * Copyright (C) 2012-2015 ROCKCHIP.\r
+ * Author: luowei <lw@rock-chips.com>\r
+ *\r
+ * This software is licensed under the terms of the GNU General Public\r
+ * License version 2, as published by the Free Software Foundation, and\r
+ * may be copied, distributed, and modified under those terms.\r
+ *\r
+ * This program is distributed in the hope that it will be useful,\r
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+ * GNU General Public License for more details.\r
+ *\r
+ */\r
+#include <linux/interrupt.h>\r
+#include <linux/i2c.h>\r
+#include <linux/slab.h>\r
+#include <linux/irq.h>\r
+#include <linux/miscdevice.h>\r
+#include <linux/gpio.h>\r
+#include <asm/uaccess.h>\r
+#include <asm/atomic.h>\r
+#include <linux/delay.h>\r
+#include <linux/input.h>\r
+#include <linux/workqueue.h>\r
+#include <linux/freezer.h>\r
+#include <mach/gpio.h>\r
+#include <mach/board.h> \r
+#ifdef CONFIG_HAS_EARLYSUSPEND\r
+#include <linux/earlysuspend.h>\r
+#endif\r
+#include <linux/sensor-dev.h>\r
+\r
+#if 0\r
+#define SENSOR_DEBUG_TYPE SENSOR_TYPE_LIGHT\r
+#define DBG(x...) if(sensor->pdata->type == SENSOR_DEBUG_TYPE) printk(x)\r
+#else\r
+#define DBG(x...)\r
+#endif\r
+\r
+#define ALS_CMD        0x01\r
+#define ALS_DT1                0x02\r
+#define ALS_DT2                0X03\r
+#define ALS_THDH1      0X04\r
+#define ALS_THDH2      0X05\r
+#define ALS_THDL1      0X06\r
+#define ALS_THDL2      0X07\r
+#define STA_TUS                0X08\r
+#define PS_CMD         0X09\r
+#define PS_DT          0X0A\r
+#define PS_THDH                0X0B\r
+#define PS_THDL                0X0C\r
+#define SW_RESET       0X80\r
+\r
+//ALS_CMD\r
+#define ALS_SD_ENABLE  (0<<0)\r
+#define ALS_SD_DISABLE (1<<0)\r
+#define ALS_INT_DISABLE        (0<<1)\r
+#define ALS_INT_ENABLE (1<<1)\r
+#define ALS_1T_100MS   (0<<2)\r
+#define ALS_2T_200MS   (1<<2)\r
+#define ALS_4T_400MS   (2<<2)\r
+#define ALS_8T_800MS   (3<<2)\r
+#define ALS_RANGE_57671        (0<<5)\r
+#define ALS_RANGE_28836        (1<<5)\r
+\r
+//PS_CMD\r
+#define PS_SD_ENABLE   (0<<0)\r
+#define PS_SD_DISABLE  (1<<0)\r
+#define PS_INT_DISABLE (0<<1)\r
+#define PS_INT_ENABLE  (1<<1)\r
+#define PS_10T_2MS     (0<<2)\r
+#define PS_15T_3MS     (1<<2)\r
+#define PS_20T_4MS     (2<<2)\r
+#define PS_25T_5MS     (3<<2)\r
+#define PS_CUR_100MA   (0<<3)\r
+#define PS_CUR_200MA   (1<<3)\r
+#define PS_SLP_10MS    (0<<4)\r
+#define PS_SLP_30MS    (1<<4)\r
+#define PS_SLP_90MS    (2<<4)\r
+#define PS_SLP_270MS   (3<<4)\r
+#define TRIG_PS_OR_LS  (0<<5)\r
+#define TRIG_PS_AND_LS (1<<5)\r
+\r
+//STA_TUS\r
+#define STA_PS_INT     (1<<4)\r
+#define        STA_ALS_INT     (1<<3)\r
+\r
+\r
+/****************operate according to sensor chip:start************/\r
+\r
+static int sensor_active(struct i2c_client *client, int enable, int rate)\r
+{\r
+       struct sensor_private_data *sensor =\r
+           (struct sensor_private_data *) i2c_get_clientdata(client);  \r
+       int result = 0;\r
+       int status = 0;\r
+\r
+       sensor->ops->ctrl_data = sensor_read_reg(client, sensor->ops->ctrl_reg);\r
+       \r
+       //register setting according to chip datasheet          \r
+       if(!enable)\r
+       {       \r
+               status = ALS_SD_DISABLE;        \r
+               sensor->ops->ctrl_data |= status;       \r
+       }\r
+       else\r
+       {\r
+               status = ~ALS_SD_DISABLE;\r
+               sensor->ops->ctrl_data &= status;\r
+       }\r
+               \r
+       DBG("%s:reg=0x%x,reg_ctrl=0x%x,enable=%d\n",__func__,sensor->ops->ctrl_reg, sensor->ops->ctrl_data, enable);\r
+       result = sensor_write_reg(client, sensor->ops->ctrl_reg, sensor->ops->ctrl_data);\r
+       if(result)\r
+               printk("%s:fail to active sensor\n",__func__);\r
+\r
+       return result;\r
+\r
+}\r
+\r
+\r
+static int sensor_init(struct i2c_client *client)\r
+{      \r
+       struct sensor_private_data *sensor =\r
+           (struct sensor_private_data *) i2c_get_clientdata(client);  \r
+       int result = 0;\r
+       \r
+       result = sensor->ops->active(client,0,0);\r
+       if(result)\r
+       {\r
+               printk("%s:line=%d,error\n",__func__,__LINE__);\r
+               return result;\r
+       }\r
+       \r
+       sensor->status_cur = SENSOR_OFF;\r
+\r
+       result = sensor_write_reg(client, SW_RESET, 0);\r
+       if(result)\r
+       {\r
+               printk("%s:line=%d,error\n",__func__,__LINE__);\r
+               return result;\r
+       }\r
+\r
+\r
+       sensor->ops->ctrl_data |= (ALS_1T_100MS | ALS_RANGE_28836);\r
+\r
+       if(sensor->pdata->irq_enable)\r
+               sensor->ops->ctrl_data |= ALS_INT_ENABLE;\r
+       else\r
+               sensor->ops->ctrl_data &= ~ALS_INT_ENABLE;\r
+       \r
+       result = sensor_write_reg(client, sensor->ops->ctrl_reg, sensor->ops->ctrl_data);\r
+       if(result)\r
+       {\r
+               printk("%s:line=%d,error\n",__func__,__LINE__);\r
+               return result;\r
+       }\r
+               \r
+       return result;\r
+}\r
+\r
+\r
+static int light_report_value(struct input_dev *input, int data)\r
+{\r
+       unsigned char index = 0;\r
+       if(data <= 10){\r
+               index = 0;goto report;\r
+       }\r
+       else if(data <= 1600){\r
+               index = 1;goto report;\r
+       }\r
+       else if(data <= 2250){\r
+               index = 2;goto report;\r
+       }\r
+       else if(data <= 3200){\r
+               index = 3;goto report;\r
+       }\r
+       else if(data <= 6400){\r
+               index = 4;goto report;\r
+       }\r
+       else if(data <= 12800){\r
+               index = 5;goto report;\r
+       }\r
+       else if(data <= 26000){\r
+               index = 6;goto report;\r
+       }\r
+       else{\r
+               index = 7;goto report;\r
+       }\r
+\r
+report:\r
+       input_report_abs(input, ABS_MISC, index);\r
+       input_sync(input);\r
+       \r
+       return index;\r
+}\r
+\r
+\r
+static int sensor_report_value(struct i2c_client *client)\r
+{\r
+       struct sensor_private_data *sensor =\r
+           (struct sensor_private_data *) i2c_get_clientdata(client);  \r
+       int result = 0;\r
+       int value = 0;\r
+       char buffer[2] = {0};   \r
+       char index = 0;\r
+       \r
+       if(sensor->ops->read_len < 2)   //sensor->ops->read_len = 2\r
+       {\r
+               printk("%s:lenth is error,len=%d\n",__func__,sensor->ops->read_len);\r
+               return -1;\r
+       }\r
+       \r
+       memset(buffer, 0, 2);\r
+\r
+       result = sensor_rx_data(client, buffer, sensor->ops->read_len);\r
+       {\r
+               printk("%s:line=%d,error\n",__func__,__LINE__);\r
+               return result;\r
+       }\r
+\r
+       value = (short) (((buffer[1]) << 8) | buffer[0]);\r
+       \r
+       index = light_report_value(sensor->input_dev, value);\r
+       \r
+       if(sensor->pdata->irq_enable)\r
+       {\r
+               if(sensor->ops->int_status_reg)\r
+               {       \r
+                       value = sensor_read_reg(client, sensor->ops->int_status_reg);\r
+               }\r
+               \r
+               if(value & STA_ALS_INT)\r
+               {\r
+                       value &= ~STA_ALS_INT;\r
+                       result = sensor_write_reg(client, sensor->ops->int_status_reg,value);   //clear int\r
+                       if(result)\r
+                       {\r
+                               printk("%s:line=%d,error\n",__func__,__LINE__);\r
+                               return result;\r
+                       }\r
+               }\r
+       }\r
+       \r
+       DBG("%s:%s result=0x%x,index=%d\n",__func__,sensor->ops->name, value,index);\r
+                       \r
+       return result;\r
+}\r
+\r
+struct sensor_operate light_ops = {\r
+       .name                           = "ls_stk3171",\r
+       .type                           = SENSOR_TYPE_LIGHT,    //sensor type and it should be correct\r
+       .id_i2c                         = LIGHT_ID_STK3171,     //i2c id number\r
+       .read_reg                       = ALS_DT1,              //read data\r
+       .read_len                       = 2,                    //data length\r
+       .id_reg                         = SENSOR_UNKNOW_DATA,   //read device id from this register\r
+       .id_data                        = SENSOR_UNKNOW_DATA,   //device id\r
+       .precision                      = 16,                   //8 bits\r
+       .ctrl_reg                       = ALS_CMD,              //enable or disable \r
+       .int_status_reg                 = STA_TUS,              //intterupt status register\r
+       .range                          = {0,10},               //range\r
+       .trig                           = IRQF_TRIGGER_LOW | IRQF_ONESHOT | IRQF_SHARED,                \r
+       .active                         = sensor_active,        \r
+       .init                           = sensor_init,\r
+       .report                         = sensor_report_value,\r
+};\r
+\r
+/****************operate according to sensor chip:end************/\r
+\r
+//function name should not be changed\r
+struct sensor_operate *light_get_ops(void)\r
+{\r
+       return &light_ops;\r
+}\r
+\r
+EXPORT_SYMBOL(light_get_ops);\r
+\r
+static int __init light_init(void)\r
+{\r
+       struct sensor_operate *ops = light_get_ops();\r
+       int result = 0;\r
+       int type = ops->type;\r
+       result = sensor_register_slave(type, NULL, NULL, light_get_ops);\r
+       printk("%s\n",__func__);\r
+       return result;\r
+}\r
+\r
+static void __exit light_exit(void)\r
+{\r
+       struct sensor_operate *ops = light_get_ops();\r
+       int type = ops->type;\r
+       sensor_unregister_slave(type, NULL, NULL, light_get_ops);\r
+}\r
+\r
+\r
+module_init(light_init);\r
+module_exit(light_exit);\r
+\r
+\r
diff --git a/drivers/input/sensors/psensor/Kconfig b/drivers/input/sensors/psensor/Kconfig
new file mode 100755 (executable)
index 0000000..289280d
--- /dev/null
@@ -0,0 +1,20 @@
+#
+# light and position sensor drivers configuration
+#
+
+menuconfig PROXIMITY_DEVICE
+       bool "proximity sensor device support"
+       default n       
+
+if PROXIMITY_DEVICE
+
+config PS_AL3006
+  bool "psensor al3006"
+       default n
+
+config PS_STK3171
+  bool "psensor stk3171"
+       default n
+
+endif
+
diff --git a/drivers/input/sensors/psensor/Makefile b/drivers/input/sensors/psensor/Makefile
new file mode 100755 (executable)
index 0000000..1da405f
--- /dev/null
@@ -0,0 +1,4 @@
+# gsensor drivers
+
+obj-$(CONFIG_PS_AL3006)                += ps_al3006.o
+obj-$(CONFIG_PS_STK3171)               += ps_stk3171.o
\ No newline at end of file
diff --git a/drivers/input/sensors/psensor/ps_al3006.c b/drivers/input/sensors/psensor/ps_al3006.c
new file mode 100755 (executable)
index 0000000..3e8f59e
--- /dev/null
@@ -0,0 +1,260 @@
+/* drivers/input/sensors/access/kxtik.c\r
+ *\r
+ * Copyright (C) 2012-2015 ROCKCHIP.\r
+ * Author: luowei <lw@rock-chips.com>\r
+ *\r
+ * This software is licensed under the terms of the GNU General Public\r
+ * License version 2, as published by the Free Software Foundation, and\r
+ * may be copied, distributed, and modified under those terms.\r
+ *\r
+ * This program is distributed in the hope that it will be useful,\r
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+ * GNU General Public License for more details.\r
+ *\r
+ */\r
+#include <linux/interrupt.h>\r
+#include <linux/i2c.h>\r
+#include <linux/slab.h>\r
+#include <linux/irq.h>\r
+#include <linux/miscdevice.h>\r
+#include <linux/gpio.h>\r
+#include <asm/uaccess.h>\r
+#include <asm/atomic.h>\r
+#include <linux/delay.h>\r
+#include <linux/input.h>\r
+#include <linux/workqueue.h>\r
+#include <linux/freezer.h>\r
+#include <mach/gpio.h>\r
+#include <mach/board.h> \r
+#ifdef CONFIG_HAS_EARLYSUSPEND\r
+#include <linux/earlysuspend.h>\r
+#endif\r
+#include <linux/sensor-dev.h>\r
+\r
+#if 0\r
+#define SENSOR_DEBUG_TYPE SENSOR_TYPE_PROXIMITY\r
+#define DBG(x...) if(sensor->pdata->type == SENSOR_DEBUG_TYPE) printk(x)\r
+#else\r
+#define DBG(x...)\r
+#endif\r
+\r
+#define CONFIG_REG        (0x00)\r
+#define TIM_CTL_REG       (0x01)\r
+#define ALS_CTL_REG       (0x02)\r
+#define INT_STATUS_REG    (0x03)\r
+#define PS_CTL_REG        (0x04)\r
+#define PS_ALS_DATA_REG   (0x05)\r
+#define ALS_WINDOWS_REG   (0x08)\r
+\r
+//enable bit[ 0-1], in register CONFIG_REG\r
+#define ONLY_ALS_EN       (0x00)\r
+#define ONLY_PROX_EN      (0x01)\r
+#define ALL_PROX_ALS_EN   (0x02)\r
+#define ALL_IDLE          (0x03)\r
+\r
+#define POWER_MODE_MASK   (0x0C)\r
+#define POWER_UP_MODE     (0x00)\r
+#define POWER_DOWN_MODE   (0x08)\r
+#define POWER_RESET_MODE  (0x0C)\r
+\r
+static int sensor_power_updown(struct i2c_client *client, int on)\r
+{\r
+       int result = 0;\r
+       char value = 0;\r
+       int i = 0;\r
+       for(i=0; i<3; i++)\r
+       {\r
+               if(!on)\r
+               {\r
+                       result = sensor_write_reg(client, CONFIG_REG, POWER_DOWN_MODE);\r
+                       if(result)\r
+                               return result;\r
+               }\r
+               else\r
+               {\r
+                       value = sensor_read_reg(client, CONFIG_REG);\r
+                       value &= ~POWER_MODE_MASK;\r
+                       value |= POWER_UP_MODE;\r
+                       result = sensor_write_reg(client, CONFIG_REG, value);\r
+                       if(result)\r
+                               return result;\r
+               }\r
+               \r
+               if(!result)\r
+               break;\r
+       }\r
+\r
+       if(i>1)\r
+       printk("%s:set %d times",__func__,i);\r
+       \r
+       return result;\r
+}\r
+\r
+\r
+/****************operate according to sensor chip:start************/\r
+\r
+static int sensor_active(struct i2c_client *client, int enable, int rate)\r
+{\r
+       struct sensor_private_data *sensor =\r
+           (struct sensor_private_data *) i2c_get_clientdata(client);  \r
+       int result = 0;\r
+       char value = 0;\r
+\r
+       sensor->ops->ctrl_data = sensor_read_reg(client, sensor->ops->ctrl_reg);\r
+       \r
+       //register setting according to chip datasheet          \r
+       if(enable)\r
+       {       \r
+               if( (sensor->ops->ctrl_data & 0x03) == ONLY_ALS_EN )\r
+               {\r
+                       value &= ~0x03;\r
+                       value |= ALL_PROX_ALS_EN;\r
+               }\r
+               else if((value & 0x03) == ALL_IDLE )\r
+               {\r
+                       value &= ~0x03;\r
+                       value |= ONLY_PROX_EN;\r
+               }\r
+               \r
+               sensor_power_updown(client, 1);\r
+       }\r
+       else\r
+       {\r
+               if( (sensor->ops->ctrl_data & 0x03) == ONLY_PROX_EN )\r
+               {\r
+                       value &= ~0x03;\r
+                       value |= ALL_IDLE;\r
+               }\r
+               else if((sensor->ops->ctrl_data & 0x03) == ALL_PROX_ALS_EN )\r
+               {\r
+                       value &= ~0x03;\r
+                       value |= ONLY_ALS_EN;\r
+               }\r
+       }\r
+       \r
+       sensor->ops->ctrl_data = value;\r
+       \r
+       DBG("%s:reg=0x%x,reg_ctrl=0x%x,enable=%d\n",__func__,sensor->ops->ctrl_reg, sensor->ops->ctrl_data, enable);\r
+       result = sensor_write_reg(client, sensor->ops->ctrl_reg, sensor->ops->ctrl_data);\r
+       if(result)\r
+               printk("%s:fail to active sensor\n",__func__);\r
+\r
+       return result;\r
+\r
+}\r
+\r
+\r
+static int sensor_init(struct i2c_client *client)\r
+{      \r
+       struct sensor_private_data *sensor =\r
+           (struct sensor_private_data *) i2c_get_clientdata(client);  \r
+       int result = 0;\r
+       char value = 0;\r
+       \r
+       sensor_power_updown(client, 0);\r
+       \r
+       result = sensor->ops->active(client,0,0);\r
+       if(result)\r
+       {\r
+               printk("%s:line=%d,error\n",__func__,__LINE__);\r
+               return result;\r
+       }\r
+       \r
+       sensor->status_cur = SENSOR_OFF;\r
+\r
+       value = 0x41;//The ADC effective resolution = 9;  Low lux threshold level = 1;\r
+       //value = 0x69; //The ADC effective resolution = 17;  Low lux threshold level = 9;
+       result = sensor_write_reg(client, ALS_CTL_REG, value);\r
+       if(result)\r
+       {\r
+               printk("%s:line=%d,error\n",__func__,__LINE__);\r
+               return result;\r
+       }\r
+
+       //value = 0x04;//0x01-0x0f; 17%->93.5% if value = 0x04,then Compensate Loss 52%
+       value = 0x02;//0x01-0x0f; 17%->93.5% if value = 0x02,then Compensate Loss 31%   \r
+       result = sensor_write_reg(client, ALS_WINDOWS_REG, value);\r
+       if(result)\r
+       {\r
+               printk("%s:line=%d,error\n",__func__,__LINE__);\r
+               return result;\r
+       }\r
+               \r
+       return result;\r
+}\r
+\r
+static int sensor_report_value(struct i2c_client *client)\r
+{\r
+       struct sensor_private_data *sensor =\r
+           (struct sensor_private_data *) i2c_get_clientdata(client);  \r
+       int result = 0;\r
+       char value = 0;\r
+\r
+       if(sensor->pdata->irq_enable)\r
+       {\r
+               if(sensor->ops->int_status_reg)\r
+               {\r
+                       value = sensor_read_reg(client, sensor->ops->int_status_reg);\r
+               }\r
+               \r
+       }\r
+\r
+       value = sensor_read_reg(client, sensor->ops->read_reg); \r
+       input_report_abs(sensor->input_dev, ABS_DISTANCE, (value>>7)?0:1);\r
+       input_sync(sensor->input_dev);\r
+       DBG("%s:%s result=0x%x,index=%d\n",__func__,sensor->ops->name, value,(value>>7)?0:1);           \r
+\r
+       return result;\r
+}\r
+\r
+struct sensor_operate proximity_ops = {\r
+       .name                           = "ps_al3006",\r
+       .type                           = SENSOR_TYPE_PROXIMITY,//sensor type and it should be correct\r
+       .id_i2c                         = PROXIMITY_ID_AL3006,  //i2c id number\r
+       .read_reg                       = PS_ALS_DATA_REG,      //read data\r
+       .read_len                       = 1,                    //data length\r
+       .id_reg                         = SENSOR_UNKNOW_DATA,   //read device id from this register\r
+       .id_data                        = SENSOR_UNKNOW_DATA,   //device id\r
+       .precision                      = 8,                    //8 bits\r
+       .ctrl_reg                       = CONFIG_REG,           //enable or disable \r
+       .int_status_reg                 = INT_STATUS_REG,       //intterupt status register\r
+       .range                          = {0,10},               //range\r
+       .trig                           = IRQF_TRIGGER_LOW | IRQF_ONESHOT | IRQF_SHARED,                \r
+       .active                         = sensor_active,        \r
+       .init                           = sensor_init,\r
+       .report                         = sensor_report_value,\r
+};\r
+\r
+/****************operate according to sensor chip:end************/\r
+\r
+//function name should not be changed\r
+struct sensor_operate *proximity_get_ops(void)\r
+{\r
+       return &proximity_ops;\r
+}\r
+\r
+EXPORT_SYMBOL(proximity_get_ops);\r
+\r
+static int __init proximity_init(void)\r
+{\r
+       struct sensor_operate *ops = proximity_get_ops();\r
+       int result = 0;\r
+       int type = ops->type;\r
+       result = sensor_register_slave(type, NULL, NULL, proximity_get_ops);\r
+       printk("%s\n",__func__);\r
+       return result;\r
+}\r
+\r
+static void __exit proximity_exit(void)\r
+{\r
+       struct sensor_operate *ops = proximity_get_ops();\r
+       int type = ops->type;\r
+       sensor_unregister_slave(type, NULL, NULL, proximity_get_ops);\r
+}\r
+\r
+\r
+module_init(proximity_init);\r
+module_exit(proximity_exit);\r
+\r
+\r
diff --git a/drivers/input/sensors/psensor/ps_stk3171.c b/drivers/input/sensors/psensor/ps_stk3171.c
new file mode 100755 (executable)
index 0000000..e5b39ee
--- /dev/null
@@ -0,0 +1,265 @@
+/* drivers/input/sensors/access/kxtik.c\r
+ *\r
+ * Copyright (C) 2012-2015 ROCKCHIP.\r
+ * Author: luowei <lw@rock-chips.com>\r
+ *\r
+ * This software is licensed under the terms of the GNU General Public\r
+ * License version 2, as published by the Free Software Foundation, and\r
+ * may be copied, distributed, and modified under those terms.\r
+ *\r
+ * This program is distributed in the hope that it will be useful,\r
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+ * GNU General Public License for more details.\r
+ *\r
+ */\r
+#include <linux/interrupt.h>\r
+#include <linux/i2c.h>\r
+#include <linux/slab.h>\r
+#include <linux/irq.h>\r
+#include <linux/miscdevice.h>\r
+#include <linux/gpio.h>\r
+#include <asm/uaccess.h>\r
+#include <asm/atomic.h>\r
+#include <linux/delay.h>\r
+#include <linux/input.h>\r
+#include <linux/workqueue.h>\r
+#include <linux/freezer.h>\r
+#include <mach/gpio.h>\r
+#include <mach/board.h> \r
+#ifdef CONFIG_HAS_EARLYSUSPEND\r
+#include <linux/earlysuspend.h>\r
+#endif\r
+#include <linux/sensor-dev.h>\r
+\r
+#if 0\r
+#define SENSOR_DEBUG_TYPE SENSOR_TYPE_PROXIMITY\r
+#define DBG(x...) if(sensor->pdata->type == SENSOR_DEBUG_TYPE) printk(x)\r
+#else\r
+#define DBG(x...)\r
+#endif\r
+\r
+#define ALS_CMD        0x01\r
+#define ALS_DT1                0x02\r
+#define ALS_DT2                0X03\r
+#define ALS_THDH1      0X04\r
+#define ALS_THDH2      0X05\r
+#define ALS_THDL1      0X06\r
+#define ALS_THDL2      0X07\r
+#define STA_TUS                0X08\r
+#define PS_CMD         0X09\r
+#define PS_DT          0X0A\r
+#define PS_THDH                0X0B\r
+#define PS_THDL                0X0C\r
+#define SW_RESET       0X80\r
+\r
+//ALS_CMD\r
+#define ALS_SD_ENABLE  (0<<0)\r
+#define ALS_SD_DISABLE (1<<0)\r
+#define ALS_INT_DISABLE        (0<<1)\r
+#define ALS_INT_ENABLE (1<<1)\r
+#define ALS_1T_100MS   (0<<2)\r
+#define ALS_2T_200MS   (1<<2)\r
+#define ALS_4T_400MS   (2<<2)\r
+#define ALS_8T_800MS   (3<<2)\r
+#define ALS_RANGE_57671        (0<<5)\r
+#define ALS_RANGE_28836        (1<<5)\r
+\r
+//PS_CMD\r
+#define PS_SD_ENABLE   (0<<0)\r
+#define PS_SD_DISABLE  (1<<0)\r
+#define PS_INT_DISABLE (0<<1)\r
+#define PS_INT_ENABLE  (1<<1)\r
+#define PS_10T_2MS     (0<<2)\r
+#define PS_15T_3MS     (1<<2)\r
+#define PS_20T_4MS     (2<<2)\r
+#define PS_25T_5MS     (3<<2)\r
+#define PS_CUR_100MA   (0<<3)\r
+#define PS_CUR_200MA   (1<<3)\r
+#define PS_SLP_10MS    (0<<4)\r
+#define PS_SLP_30MS    (1<<4)\r
+#define PS_SLP_90MS    (2<<4)\r
+#define PS_SLP_270MS   (3<<4)\r
+#define TRIG_PS_OR_LS  (0<<5)\r
+#define TRIG_PS_AND_LS (1<<5)\r
+\r
+//STA_TUS\r
+#define STA_PS_INT     (1<<4)\r
+#define        STA_ALS_INT     (1<<3)\r
+\r
+\r
+/****************operate according to sensor chip:start************/\r
+\r
+static int sensor_active(struct i2c_client *client, int enable, int rate)\r
+{\r
+       struct sensor_private_data *sensor =\r
+           (struct sensor_private_data *) i2c_get_clientdata(client);  \r
+       int result = 0;\r
+       int status = 0;\r
+\r
+       sensor->ops->ctrl_data = sensor_read_reg(client, sensor->ops->ctrl_reg);\r
+       \r
+       //register setting according to chip datasheet          \r
+       if(!enable)\r
+       {       \r
+               status = PS_SD_DISABLE; \r
+               sensor->ops->ctrl_data |= status;       \r
+       }\r
+       else\r
+       {\r
+               status = ~PS_SD_DISABLE;\r
+               sensor->ops->ctrl_data &= status;\r
+       }\r
+               \r
+       DBG("%s:reg=0x%x,reg_ctrl=0x%x,enable=%d\n",__func__,sensor->ops->ctrl_reg, sensor->ops->ctrl_data, enable);\r
+       result = sensor_write_reg(client, sensor->ops->ctrl_reg, sensor->ops->ctrl_data);\r
+       if(result)\r
+               printk("%s:fail to active sensor\n",__func__);\r
+\r
+       return result;\r
+\r
+}\r
+\r
+\r
+static int sensor_init(struct i2c_client *client)\r
+{      \r
+       struct sensor_private_data *sensor =\r
+           (struct sensor_private_data *) i2c_get_clientdata(client);  \r
+       int result = 0;\r
+       \r
+       result = sensor->ops->active(client,0,0);\r
+       if(result)\r
+       {\r
+               printk("%s:line=%d,error\n",__func__,__LINE__);\r
+               return result;\r
+       }\r
+       \r
+       sensor->status_cur = SENSOR_OFF;\r
+\r
+       result = sensor_write_reg(client, SW_RESET, 0);\r
+       if(result)\r
+       {\r
+               printk("%s:line=%d,error\n",__func__,__LINE__);\r
+               return result;\r
+       }\r
+\r
+\r
+       sensor->ops->ctrl_data |= (PS_15T_3MS| PS_SLP_90MS | TRIG_PS_OR_LS);\r
+\r
+       if(sensor->pdata->irq_enable)\r
+               sensor->ops->ctrl_data |= PS_INT_ENABLE;\r
+       else\r
+               sensor->ops->ctrl_data &= ~PS_INT_ENABLE;\r
+       \r
+       result = sensor_write_reg(client, sensor->ops->ctrl_reg, sensor->ops->ctrl_data);\r
+       if(result)\r
+       {\r
+               printk("%s:line=%d,error\n",__func__,__LINE__);\r
+               return result;\r
+       }\r
+               \r
+       return result;\r
+}\r
+\r
+\r
+\r
+static int sensor_report_value(struct i2c_client *client)\r
+{\r
+       struct sensor_private_data *sensor =\r
+           (struct sensor_private_data *) i2c_get_clientdata(client);  \r
+       int result = 0;\r
+       int value = 0;\r
+       char buffer[1] = {0};   \r
+       \r
+       if(sensor->ops->read_len < 1)   //sensor->ops->read_len = 1\r
+       {\r
+               printk("%s:lenth is error,len=%d\n",__func__,sensor->ops->read_len);\r
+               return -1;\r
+       }\r
+       \r
+       memset(buffer, 0, 1);\r
+\r
+       result = sensor_rx_data(client, buffer, sensor->ops->read_len);\r
+       {\r
+               printk("%s:line=%d,error\n",__func__,__LINE__);\r
+               return result;\r
+       }\r
+\r
+       value = buffer[0];\r
+       \r
+       input_report_abs(sensor->input_dev, ABS_DISTANCE, value?0:1);\r
+       input_sync(sensor->input_dev);\r
+       DBG("%s:%s result=0x%x,index=%d\n",__func__,sensor->ops->name, value,value?0:1);                \r
+       \r
+       if(sensor->pdata->irq_enable)\r
+       {\r
+               if(sensor->ops->int_status_reg)\r
+               {       \r
+                       value = sensor_read_reg(client, sensor->ops->int_status_reg);\r
+               }\r
+               \r
+               if(value & STA_PS_INT)\r
+               {\r
+                       value &= ~STA_PS_INT;\r
+                       result = sensor_write_reg(client, sensor->ops->int_status_reg,value);   //clear int\r
+                       if(result)\r
+                       {\r
+                               printk("%s:line=%d,error\n",__func__,__LINE__);\r
+                               return result;\r
+                       }\r
+               }\r
+       }\r
+                               \r
+       return result;\r
+}\r
+\r
+struct sensor_operate proximity_ops = {\r
+       .name                           = "ps_stk3171",\r
+       .type                           = SENSOR_TYPE_PROXIMITY,        //sensor type and it should be correct\r
+       .id_i2c                         = PROXIMITY_ID_STK3171,         //i2c id number\r
+       .read_reg                       = PS_DT,                        //read data\r
+       .read_len                       = 1,                            //data length\r
+       .id_reg                         = SENSOR_UNKNOW_DATA,           //read device id from this register\r
+       .id_data                        = SENSOR_UNKNOW_DATA,           //device id\r
+       .precision                      = 8,                            //8 bits\r
+       .ctrl_reg                       = PS_CMD,                       //enable or disable \r
+       .int_status_reg                 = STA_TUS,                      //intterupt status register\r
+       .range                          = {0,1},                        //range\r
+       .trig                           = IRQF_TRIGGER_LOW | IRQF_ONESHOT | IRQF_SHARED,                \r
+       .active                         = sensor_active,        \r
+       .init                           = sensor_init,\r
+       .report                         = sensor_report_value,\r
+};\r
+\r
+/****************operate according to sensor chip:end************/\r
+\r
+//function name should not be changed\r
+struct sensor_operate *proximity_get_ops(void)\r
+{\r
+       return &proximity_ops;\r
+}\r
+\r
+EXPORT_SYMBOL(proximity_get_ops);\r
+\r
+static int __init proximity_init(void)\r
+{\r
+       struct sensor_operate *ops = proximity_get_ops();\r
+       int result = 0;\r
+       int type = ops->type;\r
+       result = sensor_register_slave(type, NULL, NULL, proximity_get_ops);\r
+       printk("%s\n",__func__);\r
+       return result;\r
+}\r
+\r
+static void __exit proximity_exit(void)\r
+{\r
+       struct sensor_operate *ops = proximity_get_ops();\r
+       int type = ops->type;\r
+       sensor_unregister_slave(type, NULL, NULL, proximity_get_ops);\r
+}\r
+\r
+\r
+module_init(proximity_init);\r
+module_exit(proximity_exit);\r
+\r
+\r
diff --git a/drivers/input/sensors/sensor-dev.c b/drivers/input/sensors/sensor-dev.c
new file mode 100755 (executable)
index 0000000..e20270c
--- /dev/null
@@ -0,0 +1,1327 @@
+/* drivers/input/sensors/sensor-dev.c - handle all gsensor in this file\r
+ *\r
+ * Copyright (C) 2012-2015 ROCKCHIP.\r
+ * Author: luowei <lw@rock-chips.com>\r
+ *\r
+ * This software is licensed under the terms of the GNU General Public\r
+ * License version 2, as published by the Free Software Foundation, and\r
+ * may be copied, distributed, and modified under those terms.\r
+ *\r
+ * This program is distributed in the hope that it will be useful,\r
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+ * GNU General Public License for more details.\r
+ *\r
+ */\r
+\r
+#include <linux/interrupt.h>\r
+#include <linux/i2c.h>\r
+#include <linux/slab.h>\r
+#include <linux/irq.h>\r
+#include <linux/miscdevice.h>\r
+#include <linux/gpio.h>\r
+#include <asm/uaccess.h>\r
+#include <asm/atomic.h>\r
+#include <linux/delay.h>\r
+#include <linux/input.h>\r
+#include <linux/workqueue.h>\r
+#include <linux/freezer.h>\r
+#include <mach/gpio.h>\r
+#include <mach/board.h> \r
+#ifdef CONFIG_HAS_EARLYSUSPEND\r
+#include <linux/earlysuspend.h>\r
+#endif\r
+#include <linux/akm8975.h>\r
+#include <linux/l3g4200d.h>\r
+#include <linux/sensor-dev.h>\r
+\r
+#define SENSOR_ON              1\r
+#define SENSOR_OFF             0\r
+\r
+#if 0\r
+#define SENSOR_DEBUG_TYPE SENSOR_TYPE_ACCEL\r
+#define DBG(x...) if(sensor->pdata->type == SENSOR_DEBUG_TYPE) printk(x)\r
+#else\r
+#define DBG(x...)\r
+#endif\r
+\r
+struct sensor_private_data *g_sensor[SENSOR_NUM_TYPES];\r
+static struct sensor_operate *sensor_ops[SENSOR_NUM_TYPES]; \r
+\r
+static int sensor_get_id(struct i2c_client *client, int *value)\r
+{\r
+       struct sensor_private_data *sensor =\r
+           (struct sensor_private_data *) i2c_get_clientdata(client);  \r
+       int result = 0;\r
+       char temp = sensor->ops->id_reg;\r
+       int i = 0;\r
+\r
+       if(sensor->ops->id_reg >= 0)\r
+       {\r
+               for(i=0; i<3; i++)\r
+               {\r
+                       result = sensor_rx_data(client, &temp, 1);\r
+                       *value = temp;\r
+                       if(!result)\r
+                       break;\r
+               }\r
+\r
+               if(result)\r
+                       return result;\r
+\r
+               if(*value != sensor->ops->id_data)\r
+               {\r
+                       printk("%s:id=0x%x is not 0x%x\n",__func__,*value, sensor->ops->id_data);\r
+                       result = -1;\r
+               }\r
+                       \r
+               DBG("%s:devid=0x%x\n",__func__,*value);\r
+       }\r
+       \r
+       return result;\r
+}\r
+\r
+static int sensor_initial(struct i2c_client *client)\r
+{\r
+       struct sensor_private_data *sensor =\r
+           (struct sensor_private_data *) i2c_get_clientdata(client);  \r
+       int result = 0;\r
+\r
+       //register setting according to chip datasheet  \r
+       result = sensor->ops->init(client);\r
+       if(result < 0)\r
+       {\r
+               printk("%s:fail to init sensor\n",__func__);\r
+               return result;\r
+       }\r
+\r
+\r
+       DBG("%s:ctrl_data=0x%x\n",__func__,sensor->ops->ctrl_data);\r
+       \r
+       return result;\r
+\r
+}\r
+\r
+static int sensor_chip_init(struct i2c_client *client)\r
+{\r
+       struct sensor_private_data *sensor =\r
+           (struct sensor_private_data *) i2c_get_clientdata(client);  \r
+       struct sensor_operate *ops = sensor_ops[sensor->type];\r
+       int result = 0;\r
+       \r
+       if(ops)\r
+       {\r
+               sensor->ops = ops;\r
+       }\r
+       else\r
+       {\r
+               printk("%s:ops is null,sensor name is %s\n",__func__,sensor->i2c_id->name);\r
+               result = -1;\r
+               goto error;\r
+       }\r
+\r
+       if(sensor->type != ops->type)\r
+       {\r
+               printk("%s:type is different:%d,%d\n",__func__,sensor->type, sensor->type);\r
+               result = -1;\r
+               goto error;\r
+       }\r
+       \r
+       if(!ops->init || !ops->active || !ops->report)\r
+       {\r
+               printk("%s:error:some function is needed\n",__func__);          \r
+               result = -1;\r
+               goto error;\r
+       }\r
+\r
+       result = sensor_get_id(sensor->client, &sensor->devid);//get id\r
+       if(result < 0)\r
+       {       \r
+               printk("%s:fail to read devid:0x%x\n",__func__,sensor->devid);  \r
+               goto error;\r
+       }\r
+       \r
+       printk("%s:sensor->devid=0x%x,ops=0x%p\n",__func__,sensor->devid,sensor->ops);\r
+\r
+       result = sensor_initial(sensor->client);        //init sensor\r
+       if(result < 0)\r
+       {       \r
+               printk("%s:fail to init sensor\n",__func__);            \r
+               goto error;\r
+       }\r
+\r
+       return 0;\r
+\r
+error:\r
+       \r
+       return result;\r
+}\r
+\r
+static int sensor_reset_rate(struct i2c_client *client, int rate)\r
+{\r
+       struct sensor_private_data *sensor =\r
+           (struct sensor_private_data *) i2c_get_clientdata(client);  \r
+       int result = 0; \r
+       \r
+       result = sensor->ops->active(client,SENSOR_OFF,rate);\r
+       sensor->ops->init(client);\r
+       result = sensor->ops->active(client,SENSOR_ON,rate);\r
+\r
+       return result;\r
+}\r
+\r
+static int sensor_get_data(struct i2c_client *client)\r
+{\r
+       struct sensor_private_data *sensor =\r
+           (struct sensor_private_data *) i2c_get_clientdata(client);  \r
+       int result = 0;\r
+       \r
+       result = sensor->ops->report(client);\r
+       if(result)\r
+               goto error;\r
+\r
+       /* set data_ready */\r
+       atomic_set(&sensor->data_ready, 1);\r
+       /*wake up data_ready  work queue*/\r
+       wake_up(&sensor->data_ready_wq);\r
+       \r
+error:         \r
+       return result;\r
+}\r
+\r
+#if 0\r
+int sensor_get_cached_data(struct i2c_client* client, char *buffer, int length, struct sensor_axis *axis)\r
+{\r
+    struct sensor_private_data* sensor = (struct sensor_private_data *)i2c_get_clientdata(client);     \r
+    wait_event_interruptible_timeout(sensor->data_ready_wq, \r
+                                     atomic_read(&(sensor->data_ready) ),\r
+                                     msecs_to_jiffies(1000) );\r
+    if ( 0 == atomic_read(&(sensor->data_ready) ) ) {\r
+        printk("waiting 'data_ready_wq' timed out.");\r
+        goto error;\r
+    }\r
+\r
+       \r
+       mutex_lock(&sensor->data_mutex);\r
+\r
+       switch(sensor->type)\r
+       {\r
+               case SENSOR_TYPE_ACCEL:\r
+               *axis = sensor->axis;\r
+               break;\r
+\r
+               case SENSOR_TYPE_COMPASS:\r
+               memcpy(buffer, sensor->sensor_data, length);\r
+               break;\r
+       }\r
+       \r
+       mutex_unlock(&sensor->data_mutex);\r
+       \r
+    return 0;\r
+       \r
+error:\r
+       return -1;\r
+}\r
+#endif\r
+\r
+static void  sensor_delaywork_func(struct work_struct *work)\r
+{\r
+       struct delayed_work *delaywork = container_of(work, struct delayed_work, work);\r
+       struct sensor_private_data *sensor = container_of(delaywork, struct sensor_private_data, delaywork);\r
+       struct i2c_client *client = sensor->client;\r
+\r
+       mutex_lock(&sensor->sensor_mutex);      \r
+       if (sensor_get_data(client) < 0) \r
+               DBG(KERN_ERR "%s: Get data failed\n",__func__);\r
+       \r
+       if(!sensor->pdata->irq_enable)//restart work while polling\r
+       schedule_delayed_work(&sensor->delaywork, msecs_to_jiffies(sensor->pdata->poll_delay_ms));\r
+       //else\r
+       //{\r
+               //if((sensor->ops->trig == IRQF_TRIGGER_LOW) || (sensor->ops->trig == IRQF_TRIGGER_HIGH))\r
+               //enable_irq(sensor->client->irq);\r
+       //}\r
+       mutex_unlock(&sensor->sensor_mutex);\r
+       \r
+       DBG("%s:%s\n",__func__,sensor->i2c_id->name);\r
+}\r
+\r
+/*\r
+ * This is a threaded IRQ handler so can access I2C/SPI.  Since all\r
+ * interrupts are clear on read the IRQ line will be reasserted and\r
+ * the physical IRQ will be handled again if another interrupt is\r
+ * asserted while we run - in the normal course of events this is a\r
+ * rare occurrence so we save I2C/SPI reads.  We're also assuming that\r
+ * it's rare to get lots of interrupts firing simultaneously so try to\r
+ * minimise I/O.\r
+ */\r
+static irqreturn_t sensor_interrupt(int irq, void *dev_id)\r
+{\r
+       struct sensor_private_data *sensor = (struct sensor_private_data *)dev_id;\r
+\r
+       //use threaded IRQ\r
+       if (sensor_get_data(sensor->client) < 0) \r
+               DBG(KERN_ERR "%s: Get data failed\n",__func__);\r
+       msleep(sensor->pdata->poll_delay_ms);\r
+\r
+       \r
+       //if((sensor->ops->trig == IRQF_TRIGGER_LOW) || (sensor->ops->trig == IRQF_TRIGGER_HIGH))\r
+       //disable_irq_nosync(irq);\r
+       //schedule_delayed_work(&sensor->delaywork, msecs_to_jiffies(sensor->pdata->poll_delay_ms));\r
+       DBG("%s:irq=%d\n",__func__,irq);\r
+       return IRQ_HANDLED;\r
+}\r
+\r
+\r
+static int sensor_irq_init(struct i2c_client *client)\r
+{\r
+       struct sensor_private_data *sensor =\r
+           (struct sensor_private_data *) i2c_get_clientdata(client);  \r
+       int result = 0;\r
+       int irq;\r
+       if((sensor->pdata->irq_enable)&&(sensor->ops->trig != SENSOR_UNKNOW_DATA))\r
+       {\r
+               //INIT_DELAYED_WORK(&sensor->delaywork, sensor_delaywork_func);\r
+               if(sensor->pdata->poll_delay_ms < 0)\r
+                       sensor->pdata->poll_delay_ms = 30;\r
+               \r
+               result = gpio_request(client->irq, sensor->i2c_id->name);\r
+               if (result)\r
+               {\r
+                       printk("%s:fail to request gpio :%d\n",__func__,client->irq);\r
+               }\r
+       \r
+               gpio_pull_updown(client->irq, PullEnable);\r
+               irq = gpio_to_irq(client->irq);\r
+               //result = request_irq(irq, sensor_interrupt, sensor->ops->trig, client->dev.driver->name, sensor);\r
+               result = request_threaded_irq(irq, NULL, sensor_interrupt, sensor->ops->trig, client->dev.driver->name, sensor);\r
+               if (result) {\r
+                       printk(KERN_ERR "%s:fail to request irq = %d, ret = 0x%x\n",__func__, irq, result);            \r
+                       goto error;            \r
+               }\r
+               client->irq = irq;\r
+               if((sensor->pdata->type == SENSOR_TYPE_GYROSCOPE))\r
+               disable_irq_nosync(client->irq);//disable irq\r
+               printk("%s:use irq=%d\n",__func__,irq);\r
+       }\r
+       else if(!sensor->pdata->irq_enable)\r
+       {               \r
+               INIT_DELAYED_WORK(&sensor->delaywork, sensor_delaywork_func);\r
+               if(sensor->pdata->poll_delay_ms < 0)\r
+                       sensor->pdata->poll_delay_ms = 30;\r
+               \r
+               printk("%s:use polling,delay=%d ms\n",__func__,sensor->pdata->poll_delay_ms);\r
+       }\r
+\r
+error: \r
+       return result;\r
+}\r
+\r
+\r
+static void sensor_suspend(struct early_suspend *h)\r
+{\r
+       struct sensor_private_data *sensor = \r
+                       container_of(h, struct sensor_private_data, early_suspend);\r
+       \r
+       if(sensor->ops->suspend)\r
+               sensor->ops->suspend(sensor->client);\r
+\r
+}\r
+\r
+static void sensor_resume(struct early_suspend *h)\r
+{\r
+       struct sensor_private_data *sensor = \r
+                       container_of(h, struct sensor_private_data, early_suspend);\r
+\r
+       if(sensor->ops->resume)\r
+               sensor->ops->resume(sensor->client);\r
+}\r
+\r
+static int gsensor_dev_open(struct inode *inode, struct file *file)\r
+{\r
+       //struct sensor_private_data *sensor = g_sensor[SENSOR_TYPE_ACCEL];     \r
+       //struct i2c_client *client = sensor->client;\r
+\r
+       int result = 0;\r
+\r
+\r
+       return result;\r
+}\r
+\r
+\r
+static int gsensor_dev_release(struct inode *inode, struct file *file)\r
+{\r
+       //struct sensor_private_data *sensor = g_sensor[SENSOR_TYPE_ACCEL];     \r
+       //struct i2c_client *client = sensor->client;\r
+\r
+       int result = 0;\r
+\r
+\r
+       return result;\r
+}\r
+\r
+/* ioctl - I/O control */\r
+static long gsensor_dev_ioctl(struct file *file,\r
+                         unsigned int cmd, unsigned long arg)\r
+{\r
+       struct sensor_private_data *sensor = g_sensor[SENSOR_TYPE_ACCEL];\r
+       struct i2c_client *client = sensor->client;\r
+       void __user *argp = (void __user *)arg;\r
+       struct sensor_axis axis = {0};\r
+       char rate;\r
+       int result = 0;\r
+\r
+       switch (cmd) {\r
+       case GSENSOR_IOCTL_APP_SET_RATE:\r
+               if (copy_from_user(&rate, argp, sizeof(rate)))\r
+               {\r
+                       result = -EFAULT;\r
+                       goto error;\r
+               }\r
+               break;\r
+       default:\r
+               break;\r
+       }
+
+       switch (cmd) {
+       case GSENSOR_IOCTL_START:       \r
+               DBG("%s:GSENSOR_IOCTL_START start,status=%d\n", __func__,sensor->status_cur);\r
+               mutex_lock(&sensor->operation_mutex);   \r
+               if(++sensor->start_count == 1)\r
+               {\r
+                       if(sensor->status_cur == SENSOR_OFF)\r
+                       {\r
+                               atomic_set(&(sensor->data_ready), 0);\r
+                               if ( (result = sensor->ops->active(client, 1, 0) ) < 0 ) {\r
+                                       mutex_unlock(&sensor->operation_mutex);\r
+                                       printk("%s:fail to active sensor,ret=%d\n",__func__,result);         \r
+                                       goto error;           \r
+                               }                       \r
+                               if(sensor->pdata->irq_enable)\r
+                               {\r
+                                       //printk("%s:enable irq,irq=%d\n",__func__,client->irq);\r
+                                       //enable_irq(client->irq);      //enable irq\r
+                               }       \r
+                               else\r
+                               {\r
+                                       PREPARE_DELAYED_WORK(&sensor->delaywork, sensor_delaywork_func);\r
+                                       schedule_delayed_work(&sensor->delaywork, msecs_to_jiffies(sensor->pdata->poll_delay_ms));\r
+                               }\r
+                               sensor->status_cur = SENSOR_ON;\r
+                       }       \r
+               }\r
+               mutex_unlock(&sensor->operation_mutex);\r
+               DBG("%s:GSENSOR_IOCTL_START OK\n", __func__);\r
+               break;\r
+
+       case GSENSOR_IOCTL_CLOSE:                               \r
+               DBG("%s:GSENSOR_IOCTL_CLOSE start,status=%d\n", __func__,sensor->status_cur);\r
+               mutex_lock(&sensor->operation_mutex);           \r
+               if(--sensor->start_count == 0)\r
+               {\r
+                       if(sensor->status_cur == SENSOR_ON)\r
+                       {\r
+                               atomic_set(&(sensor->data_ready), 0);\r
+                               if ( (result = sensor->ops->active(client, 0, 0) ) < 0 ) {\r
+                                       mutex_unlock(&sensor->operation_mutex);              \r
+                                       goto error;\r
+                               }\r
+                               \r
+                               if(sensor->pdata->irq_enable)\r
+                               {                               \r
+                                       //printk("%s:disable irq,irq=%d\n",__func__,client->irq);\r
+                                       //disable_irq_nosync(client->irq);//disable irq\r
+                               }\r
+                               else\r
+                               cancel_delayed_work_sync(&sensor->delaywork);           \r
+                               sensor->status_cur = SENSOR_OFF;\r
+                       }\r
+                       \r
+                       DBG("%s:GSENSOR_IOCTL_CLOSE OK\n", __func__);\r
+               }\r
+               \r
+               mutex_unlock(&sensor->operation_mutex); \r
+               break;\r
+
+       case GSENSOR_IOCTL_APP_SET_RATE:                \r
+               DBG("%s:GSENSOR_IOCTL_APP_SET_RATE start\n", __func__);         \r
+               mutex_lock(&sensor->operation_mutex);   \r
+               result = sensor_reset_rate(client, rate);\r
+               if (result < 0)\r
+               goto error;\r
+               if(sensor->status_cur == SENSOR_OFF)\r
+               {               \r
+                       if(sensor->pdata->irq_enable)\r
+                       {\r
+                               //printk("%s:enable irq,irq=%d\n",__func__,client->irq);\r
+                               //enable_irq(client->irq);      //enable irq\r
+                       }       \r
+                       else\r
+                       {\r
+                               PREPARE_DELAYED_WORK(&sensor->delaywork, sensor_delaywork_func);\r
+                               schedule_delayed_work(&sensor->delaywork, msecs_to_jiffies(sensor->pdata->poll_delay_ms));\r
+                       }\r
+                       sensor->status_cur = SENSOR_ON;\r
+               }                       \r
+               mutex_unlock(&sensor->operation_mutex); \r
+               DBG("%s:GSENSOR_IOCTL_APP_SET_RATE OK\n", __func__);\r
+               break;\r
+               \r
+       case GSENSOR_IOCTL_GETDATA:\r
+               mutex_lock(&sensor->data_mutex);\r
+               memcpy(&axis, &sensor->axis, sizeof(sensor->axis));     //get data from buffer\r
+               mutex_unlock(&sensor->data_mutex);              \r
+               break;\r
+       default:\r
+               result = -ENOTTY;\r
+       goto error;\r
+       }
+
+       switch (cmd) {
+       case GSENSOR_IOCTL_GETDATA:\r
+               if ( copy_to_user(argp, &axis, sizeof(axis) ) ) {\r
+                   printk("failed to copy sense data to user space.");\r
+                               result = -EFAULT;                       \r
+                               goto error;\r
+               }               \r
+               DBG("%s:GSENSOR_IOCTL_GETDATA OK\n", __func__);\r
+               break;
+       default:
+               break;
+       }\r
+       \r
+error:\r
+       return result;\r
+}\r
+\r
+\r
+static int compass_dev_open(struct inode *inode, struct file *file)\r
+{\r
+       //struct sensor_private_data *sensor = g_sensor[SENSOR_TYPE_COMPASS];\r
+       //struct i2c_client *client = sensor->client;\r
+       int result = 0;\r
+       \r
+       //to do\r
+       return result;\r
+}\r
+\r
+\r
+static int compass_dev_release(struct inode *inode, struct file *file)\r
+{\r
+       //struct sensor_private_data *sensor = g_sensor[SENSOR_TYPE_COMPASS];\r
+       //struct i2c_client *client = sensor->client;   \r
+       int result = 0;\r
+\r
+       //to do\r
+       return result;\r
+}\r
+\r
+\r
+/* ioctl - I/O control */\r
+static long compass_dev_ioctl(struct file *file,\r
+                         unsigned int cmd, unsigned long arg)\r
+{\r
+       //struct sensor_private_data *sensor = g_sensor[SENSOR_TYPE_COMPASS];\r
+       //struct i2c_client *client = sensor->client;\r
+       //void __user *argp = (void __user *)arg;\r
+       int result = 0;\r
+       \r
+       //to do\r
+       return result;\r
+}\r
+\r
+static int gyro_dev_open(struct inode *inode, struct file *file)\r
+{\r
+       //struct sensor_private_data *sensor = g_sensor[SENSOR_TYPE_GYROSCOPE];\r
+       //struct i2c_client *client = sensor->client;\r
+\r
+       int result = 0;\r
+\r
+\r
+       return result;\r
+}\r
+\r
+\r
+static int gyro_dev_release(struct inode *inode, struct file *file)\r
+{\r
+       //struct sensor_private_data *sensor = g_sensor[SENSOR_TYPE_GYROSCOPE];\r
+       //struct i2c_client *client = sensor->client;\r
+\r
+       int result = 0;\r
+\r
+\r
+       return result;\r
+}\r
+\r
+\r
+/* ioctl - I/O control */\r
+static long gyro_dev_ioctl(struct file *file,\r
+                         unsigned int cmd, unsigned long arg)\r
+{\r
+       struct sensor_private_data *sensor = g_sensor[SENSOR_TYPE_GYROSCOPE];   \r
+       struct i2c_client *client = sensor->client;     \r
+       void __user *argp = (void __user *)arg;\r
+       int result = 0;\r
+       char rate;\r
+       switch (cmd) {\r
+       case L3G4200D_IOCTL_GET_ENABLE: \r
+               result = !sensor->status_cur;\r
+               if (copy_to_user(argp, &result, sizeof(result)))\r
+               {\r
+                       printk("%s:failed to copy status to user space.\n",__FUNCTION__);\r
+                       return -EFAULT;\r
+               }\r
+               \r
+               DBG("%s :L3G4200D_IOCTL_GET_ENABLE,status=%d\n",__FUNCTION__,result);   \r
+               break;\r
+       case L3G4200D_IOCTL_SET_ENABLE:                 \r
+               DBG("%s :L3G4200D_IOCTL_SET_ENABLE,flag=%d\n",__FUNCTION__,*(unsigned int *)argp);\r
+               mutex_lock(&sensor->operation_mutex);   \r
+               if(*(unsigned int *)argp)\r
+               {\r
+                       if(sensor->status_cur == SENSOR_OFF)\r
+                       {\r
+                               if ( (result = sensor->ops->active(client, 1, ODR100_BW12_5) ) < 0 ) {\r
+                               mutex_unlock(&sensor->operation_mutex);\r
+                               printk("%s:fail to active sensor,ret=%d\n",__func__,result);         \r
+                               goto error;           \r
+                               }                       \r
+                               if(sensor->pdata->irq_enable)\r
+                               {\r
+                                       DBG("%s:enable irq,irq=%d\n",__func__,client->irq);\r
+                                       enable_irq(client->irq);        //enable irq\r
+                               }       \r
+                               else\r
+                               {\r
+                                       PREPARE_DELAYED_WORK(&sensor->delaywork, sensor_delaywork_func);\r
+                                       schedule_delayed_work(&sensor->delaywork, msecs_to_jiffies(sensor->pdata->poll_delay_ms));\r
+                               }\r
+                               sensor->status_cur = SENSOR_ON;\r
+                       }       \r
+               }\r
+               else\r
+               {\r
+                       if(sensor->status_cur == SENSOR_ON)\r
+                       {\r
+                               if ( (result = sensor->ops->active(client, 0, 0) ) < 0 ) {\r
+                               mutex_unlock(&sensor->operation_mutex);              \r
+                               goto error;\r
+                               }\r
+                               \r
+                               if(sensor->pdata->irq_enable)\r
+                               {                               \r
+                                       DBG("%s:disable irq,irq=%d\n",__func__,client->irq);\r
+                                       disable_irq_nosync(client->irq);//disable irq\r
+                               }\r
+                               else\r
+                               cancel_delayed_work_sync(&sensor->delaywork);           \r
+                               sensor->status_cur = SENSOR_OFF;\r
+                       }\r
+               }\r
+       \r
+               result = sensor->status_cur;\r
+               if (copy_to_user(argp, &result, sizeof(result)))\r
+               {\r
+                       printk("%s:failed to copy sense data to user space.\n",__FUNCTION__);\r
+                       return -EFAULT;\r
+               }\r
+\r
+               mutex_unlock(&sensor->operation_mutex);\r
+               DBG("%s:L3G4200D_IOCTL_SET_ENABLE OK\n", __func__);\r
+               break;\r
+       case L3G4200D_IOCTL_SET_DELAY:                                  \r
+               mutex_lock(&sensor->operation_mutex);\r
+               if (copy_from_user(&rate, argp, sizeof(rate)))\r
+               return -EFAULT;\r
+               if(sensor->status_cur == SENSOR_OFF)\r
+               {\r
+                       if ( (result = sensor->ops->active(client, 1, rate) ) < 0 ) {\r
+                       mutex_unlock(&sensor->operation_mutex);\r
+                       printk("%s:fail to active sensor,ret=%d\n",__func__,result);         \r
+                       goto error;           \r
+                       }\r
+                       \r
+                       if(sensor->pdata->irq_enable)\r
+                       {\r
+                               DBG("%s:enable irq,irq=%d\n",__func__,client->irq);\r
+                               enable_irq(client->irq);        //enable irq\r
+                       }       \r
+                       else\r
+                       {\r
+                               PREPARE_DELAYED_WORK(&sensor->delaywork, sensor_delaywork_func);\r
+                               schedule_delayed_work(&sensor->delaywork, msecs_to_jiffies(sensor->pdata->poll_delay_ms));\r
+                       }\r
+                       sensor->status_cur = SENSOR_ON;\r
+               }       \r
+               \r
+               mutex_unlock(&sensor->operation_mutex);\r
+               DBG("%s :L3G4200D_IOCTL_SET_DELAY,rate=%d\n",__FUNCTION__,rate);\r
+               break;\r
+\r
+       default:\r
+               printk("%s:error,cmd=0x%x\n",__func__,cmd);\r
+               return -ENOTTY;\r
+       }\r
+       \r
+       DBG("%s:line=%d,cmd=0x%x\n",__func__,__LINE__,cmd);\r
+\r
+error:\r
+       return result;\r
+}\r
+\r
+static int light_dev_open(struct inode *inode, struct file *file)\r
+{\r
+       //struct sensor_private_data *sensor = g_sensor[SENSOR_TYPE_LIGHT];\r
+       //struct i2c_client *client = sensor->client;   \r
+       int result = 0; \r
+\r
+\r
+       return result;\r
+}\r
+\r
+\r
+\r
+\r
+static int light_dev_release(struct inode *inode, struct file *file)\r
+{\r
+       //struct sensor_private_data *sensor = g_sensor[SENSOR_TYPE_LIGHT];\r
+       //struct i2c_client *client = sensor->client;   \r
+       int result = 0;\r
+\r
+\r
+       return result;\r
+}\r
+\r
+\r
+/* ioctl - I/O control */\r
+static long light_dev_ioctl(struct file *file,\r
+                         unsigned int cmd, unsigned long arg)\r
+{\r
+       struct sensor_private_data *sensor = g_sensor[SENSOR_TYPE_LIGHT];\r
+       struct i2c_client *client = sensor->client;\r
+       unsigned int *argp = (unsigned int *)arg;       \r
+       int result = 0;\r
+\r
+       switch(cmd)\r
+       {\r
+               case LIGHTSENSOR_IOCTL_GET_ENABLED:
+                       *argp = sensor->status_cur;\r
+                       break;
+               case LIGHTSENSOR_IOCTL_ENABLE:          \r
+                       DBG("%s:LIGHTSENSOR_IOCTL_ENABLE start\n", __func__);\r
+                       mutex_lock(&sensor->operation_mutex);    \r
+                       if(*(unsigned int *)argp)\r
+                       {\r
+                               if(sensor->status_cur == SENSOR_OFF)\r
+                               {\r
+                                       if ( (result = sensor->ops->active(client, SENSOR_ON, 0) ) < 0 ) {\r
+                                       mutex_unlock(&sensor->operation_mutex);\r
+                                       printk("%s:fail to active sensor,ret=%d\n",__func__,result);         \r
+                                       goto error;           \r
+                                       }       \r
+                                       \r
+                                       if(!sensor->pdata->irq_enable)\r
+                                       {\r
+                                               PREPARE_DELAYED_WORK(&sensor->delaywork, sensor_delaywork_func);\r
+                                               schedule_delayed_work(&sensor->delaywork, msecs_to_jiffies(sensor->pdata->poll_delay_ms));\r
+                                       }\r
+                                       sensor->status_cur = SENSOR_ON;\r
+                               }       \r
+                       }\r
+                       else\r
+                       {\r
+                               if(sensor->status_cur == SENSOR_ON)\r
+                               {\r
+                                       if ( (result = sensor->ops->active(client, SENSOR_OFF, 0) ) < 0 ) {\r
+                                       mutex_unlock(&sensor->operation_mutex);              \r
+                                       goto error;\r
+                                       }\r
+                                       \r
+                                       if(!sensor->pdata->irq_enable)\r
+                                       cancel_delayed_work_sync(&sensor->delaywork);           \r
+                                       sensor->status_cur = SENSOR_OFF;\r
+                               }\r
+                       }\r
+                       mutex_unlock(&sensor->operation_mutex);\r
+                       DBG("%s:LIGHTSENSOR_IOCTL_ENABLE OK\n", __func__);\r
+                       break;\r
+               \r
+               default:\r
+                       break;\r
+       }\r
+       \r
+error:\r
+       return result;\r
+}\r
+\r
+\r
+static int proximity_dev_open(struct inode *inode, struct file *file)\r
+{\r
+       //struct sensor_private_data *sensor = g_sensor[SENSOR_TYPE_PROXIMITY];\r
+       //struct i2c_client *client = sensor->client;   \r
+       int result = 0;\r
+\r
+\r
+       return result;\r
+}\r
+\r
+\r
+static int proximity_dev_release(struct inode *inode, struct file *file)\r
+{\r
+       //struct sensor_private_data *sensor = g_sensor[SENSOR_TYPE_PROXIMITY];\r
+       //struct i2c_client *client = sensor->client;   \r
+       int result = 0;\r
+\r
+\r
+       return result;\r
+}\r
+\r
+\r
+/* ioctl - I/O control */\r
+static long proximity_dev_ioctl(struct file *file,\r
+                         unsigned int cmd, unsigned long arg)\r
+{\r
+       struct sensor_private_data *sensor = g_sensor[SENSOR_TYPE_PROXIMITY];\r
+       struct i2c_client *client = sensor->client;     \r
+       unsigned int *argp = (unsigned int *)arg;       \r
+       int result = 0;\r
+       switch(cmd)\r
+       {\r
+               case PSENSOR_IOCTL_GET_ENABLED:\r
+                       *argp = sensor->status_cur;\r
+                       break;
+               case PSENSOR_IOCTL_ENABLE:              \r
+                       DBG("%s:PSENSOR_IOCTL_ENABLE start\n", __func__);\r
+                       mutex_lock(&sensor->operation_mutex);    \r
+                       if(*(unsigned int *)argp)\r
+                       {\r
+                               if(sensor->status_cur == SENSOR_OFF)\r
+                               {\r
+                                       if ( (result = sensor->ops->active(client, SENSOR_ON, 0) ) < 0 ) {\r
+                                       mutex_unlock(&sensor->operation_mutex);\r
+                                       printk("%s:fail to active sensor,ret=%d\n",__func__,result);         \r
+                                       goto error;           \r
+                                       }\r
+                                       \r
+                                       if(!sensor->pdata->irq_enable)\r
+                                       {\r
+                                               PREPARE_DELAYED_WORK(&sensor->delaywork, sensor_delaywork_func);\r
+                                               schedule_delayed_work(&sensor->delaywork, msecs_to_jiffies(sensor->pdata->poll_delay_ms));\r
+                                       }\r
+                                       sensor->status_cur = SENSOR_ON;\r
+                               }       \r
+                       }\r
+                       else\r
+                       {\r
+                               if(sensor->status_cur == SENSOR_ON)\r
+                               {\r
+                                       if ( (result = sensor->ops->active(client, SENSOR_OFF, 0) ) < 0 ) {\r
+                                       mutex_unlock(&sensor->operation_mutex);              \r
+                                       goto error;\r
+                                       }\r
+                                       if(!sensor->pdata->irq_enable)\r
+                                       cancel_delayed_work_sync(&sensor->delaywork);           \r
+                                       sensor->status_cur = SENSOR_OFF;\r
+                               }\r
+                       }\r
+                       mutex_unlock(&sensor->operation_mutex);\r
+                       DBG("%s:PSENSOR_IOCTL_ENABLE OK\n", __func__);\r
+                       break;\r
+               \r
+               default:\r
+                       break;\r
+       }\r
+       \r
+error:\r
+       return result;\r
+}\r
+\r
+static int temperature_dev_open(struct inode *inode, struct file *file)\r
+{\r
+       //struct sensor_private_data *sensor = g_sensor[SENSOR_TYPE_TEMPERATURE];\r
+       //struct i2c_client *client = sensor->client;\r
+\r
+       int result = 0;\r
+\r
+\r
+       return result;\r
+}\r
+\r
+\r
+static int temperature_dev_release(struct inode *inode, struct file *file)\r
+{\r
+       //struct sensor_private_data *sensor = g_sensor[SENSOR_TYPE_TEMPERATURE];\r
+       //struct i2c_client *client = sensor->client;\r
+\r
+       int result = 0;\r
+\r
+\r
+       return result;\r
+}\r
+\r
+\r
+/* ioctl - I/O control */\r
+static long temperature_dev_ioctl(struct file *file,\r
+                         unsigned int cmd, unsigned long arg)\r
+{\r
+       //struct sensor_private_data *sensor = g_sensor[SENSOR_TYPE_TEMPERATURE];\r
+       //struct i2c_client *client = sensor->client;\r
+       //void __user *argp = (void __user *)arg;\r
+       int result = 0;\r
+       \r
+\r
+       return result;\r
+}\r
+\r
+\r
+static int sensor_misc_device_register(struct sensor_private_data *sensor, int type)\r
+{\r
+       int result = 0;\r
+       \r
+       switch(type)\r
+       {\r
+               case SENSOR_TYPE_ACCEL:\r
+                       if(!sensor->ops->misc_dev)\r
+                       {\r
+                               sensor->fops.owner = THIS_MODULE;\r
+                               sensor->fops.unlocked_ioctl = gsensor_dev_ioctl;\r
+                               sensor->fops.open = gsensor_dev_open;\r
+                               sensor->fops.release = gsensor_dev_release;\r
+\r
+                               sensor->miscdev.minor = MISC_DYNAMIC_MINOR;\r
+                               sensor->miscdev.name = "mma8452_daemon";\r
+                               sensor->miscdev.fops = &sensor->fops;\r
+                       }\r
+                       else\r
+                       {\r
+                               memcpy(&sensor->miscdev, sensor->ops->misc_dev, sizeof(*sensor->ops->misc_dev));\r
+\r
+                       }\r
+                               \r
+                       break;\r
+\r
+               case SENSOR_TYPE_COMPASS:                       \r
+                       if(!sensor->ops->misc_dev)\r
+                       {\r
+                               sensor->fops.owner = THIS_MODULE;\r
+                               sensor->fops.unlocked_ioctl = compass_dev_ioctl;\r
+                               sensor->fops.open = compass_dev_open;\r
+                               sensor->fops.release = compass_dev_release;\r
+\r
+                               sensor->miscdev.minor = MISC_DYNAMIC_MINOR;\r
+                               sensor->miscdev.name = "compass";\r
+                               sensor->miscdev.fops = &sensor->fops;\r
+                       }\r
+                       else\r
+                       {\r
+                               memcpy(&sensor->miscdev, sensor->ops->misc_dev, sizeof(*sensor->ops->misc_dev));\r
+\r
+                       }\r
+\r
+                       break;\r
+\r
+               case SENSOR_TYPE_GYROSCOPE:                     \r
+                       if(!sensor->ops->misc_dev)\r
+                       {\r
+                               sensor->fops.owner = THIS_MODULE;\r
+                               sensor->fops.unlocked_ioctl = gyro_dev_ioctl;\r
+                               sensor->fops.open = gyro_dev_open;\r
+                               sensor->fops.release = gyro_dev_release;\r
+\r
+                               sensor->miscdev.minor = MISC_DYNAMIC_MINOR;\r
+                               sensor->miscdev.name = "gyrosensor";\r
+                               sensor->miscdev.fops = &sensor->fops;\r
+                       }\r
+                       else\r
+                       {\r
+                               memcpy(&sensor->miscdev, sensor->ops->misc_dev, sizeof(*sensor->ops->misc_dev));\r
+\r
+                       }\r
+                       \r
+                       break;\r
+\r
+               case SENSOR_TYPE_LIGHT:\r
+                       if(!sensor->ops->misc_dev)\r
+                       {\r
+                               sensor->fops.owner = THIS_MODULE;\r
+                               sensor->fops.unlocked_ioctl = light_dev_ioctl;\r
+                               sensor->fops.open = light_dev_open;\r
+                               sensor->fops.release = light_dev_release;\r
+\r
+                               sensor->miscdev.minor = MISC_DYNAMIC_MINOR;\r
+                               sensor->miscdev.name = "lightsensor";\r
+                               sensor->miscdev.fops = &sensor->fops;\r
+                       }       \r
+                       else\r
+                       {\r
+                               memcpy(&sensor->miscdev, sensor->ops->misc_dev, sizeof(*sensor->ops->misc_dev));\r
+\r
+                       }\r
+                       break;\r
+               \r
+               case SENSOR_TYPE_PROXIMITY:\r
+                       if(!sensor->ops->misc_dev)\r
+                       {\r
+                               sensor->fops.owner = THIS_MODULE;\r
+                               sensor->fops.unlocked_ioctl = proximity_dev_ioctl;\r
+                               sensor->fops.open = proximity_dev_open;\r
+                               sensor->fops.release = proximity_dev_release;\r
+\r
+                               sensor->miscdev.minor = MISC_DYNAMIC_MINOR;\r
+                               sensor->miscdev.name = "psensor";\r
+                               sensor->miscdev.fops = &sensor->fops;\r
+                       }       \r
+                       else\r
+                       {\r
+                               memcpy(&sensor->miscdev, sensor->ops->misc_dev, sizeof(*sensor->ops->misc_dev));\r
+\r
+                       }\r
+                       break;\r
+\r
+               case SENSOR_TYPE_TEMPERATURE:\r
+                       if(!sensor->ops->misc_dev)\r
+                       {\r
+                               sensor->fops.owner = THIS_MODULE;\r
+                               sensor->fops.unlocked_ioctl = temperature_dev_ioctl;\r
+                               sensor->fops.open = temperature_dev_open;\r
+                               sensor->fops.release = temperature_dev_release;\r
+\r
+                               sensor->miscdev.minor = MISC_DYNAMIC_MINOR;\r
+                               sensor->miscdev.name = "temperature";\r
+                               sensor->miscdev.fops = &sensor->fops;\r
+                       }       \r
+                       else\r
+                       {\r
+                               memcpy(&sensor->miscdev, sensor->ops->misc_dev, sizeof(*sensor->ops->misc_dev));\r
+\r
+                       }\r
+                               \r
+                       break;\r
+\r
+               default:\r
+                       printk("%s:unknow sensor type=%d\n",__func__,type);\r
+                       result = -1;\r
+                       goto error;\r
+       }\r
+                       \r
+       sensor->miscdev.parent = &sensor->client->dev;\r
+       result = misc_register(&sensor->miscdev);\r
+       if (result < 0) {\r
+               dev_err(&sensor->client->dev,\r
+                       "fail to register misc device %s\n", sensor->miscdev.name);\r
+               goto error;\r
+       }\r
+       \r
+       printk("%s:miscdevice: %s\n",__func__,sensor->miscdev.name);\r
+\r
+error: \r
+       \r
+       return result;\r
+\r
+}\r
+\r
+int sensor_register_slave(int type,struct i2c_client *client,\r
+                       struct sensor_platform_data *slave_pdata,\r
+                       struct sensor_operate *(*get_sensor_ops)(void))\r
+{\r
+       int result = 0;\r
+       sensor_ops[type] = get_sensor_ops();\r
+       printk("%s:%s\n",__func__,sensor_ops[type]->name);\r
+       return result;\r
+}\r
+\r
+\r
+int sensor_unregister_slave(int type,struct i2c_client *client,\r
+                       struct sensor_platform_data *slave_pdata,\r
+                       struct sensor_operate *(*get_sensor_ops)(void))\r
+{\r
+       int result = 0;\r
+       printk("%s:%s\n",__func__,sensor_ops[type]->name);\r
+       sensor_ops[type] = NULL;        \r
+       return result;\r
+}\r
+\r
+\r
+int sensor_probe(struct i2c_client *client, const struct i2c_device_id *devid)\r
+{\r
+       struct sensor_private_data *sensor =\r
+           (struct sensor_private_data *) i2c_get_clientdata(client);\r
+       struct sensor_platform_data *pdata;\r
+       int result = 0;\r
+       int type = 0;\r
+       dev_info(&client->adapter->dev, "%s: %s,0x%x\n", __func__, devid->name,(unsigned int)client);\r
+\r
+       if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {\r
+               result = -ENODEV;\r
+               goto out_no_free;\r
+       }\r
+\r
+       pdata = client->dev.platform_data;\r
+       if (!pdata) {\r
+               dev_err(&client->adapter->dev,\r
+                       "Missing platform data for slave %s\n", devid->name);\r
+               result = -EFAULT;\r
+               goto out_no_free;\r
+       }\r
+\r
+       sensor = kzalloc(sizeof(*sensor), GFP_KERNEL);\r
+       if (!sensor) {\r
+               result = -ENOMEM;\r
+               goto out_no_free;\r
+       }\r
+\r
+       type= pdata->type;      \r
+       \r
+       if((type >= SENSOR_NUM_TYPES) || (type <= SENSOR_TYPE_NULL))\r
+       {       \r
+               dev_err(&client->adapter->dev, "sensor type is error %d\n", pdata->type);\r
+               result = -EFAULT;\r
+               goto out_no_free;       \r
+       }\r
+       \r
+       i2c_set_clientdata(client, sensor);\r
+       sensor->client = client;        \r
+       sensor->pdata = pdata;  \r
+       sensor->type = type;\r
+       sensor->i2c_id = (struct i2c_device_id *)devid;\r
+\r
+       if (pdata->init_platform_hw) {\r
+               result = pdata->init_platform_hw();\r
+               if (result < 0)\r
+                       goto out_free_memory;\r
+       }\r
+\r
+       memset(&(sensor->axis), 0, sizeof(struct sensor_axis) );\r
+       atomic_set(&(sensor->data_ready), 0);\r
+       init_waitqueue_head(&(sensor->data_ready_wq));\r
+       mutex_init(&sensor->data_mutex);        \r
+       mutex_init(&sensor->operation_mutex);   \r
+       mutex_init(&sensor->sensor_mutex);\r
+       mutex_init(&sensor->i2c_mutex);\r
+\r
+       sensor->status_cur = SENSOR_OFF;\r
+       sensor->axis.x = 0;\r
+       sensor->axis.y = 0;\r
+       sensor->axis.z = 0;\r
+       \r
+       result = sensor_chip_init(sensor->client);\r
+       if(result < 0)\r
+               goto out_free_memory;\r
+       \r
+       sensor->input_dev = input_allocate_device();\r
+       if (!sensor->input_dev) {\r
+               result = -ENOMEM;\r
+               dev_err(&client->dev,\r
+                       "Failed to allocate input device %s\n", sensor->input_dev->name);\r
+               goto out_free_memory;\r
+       }       \r
+\r
+       switch(type)\r
+       {\r
+               case SENSOR_TYPE_ACCEL: \r
+                       sensor->input_dev->name = "gsensor";\r
+                       set_bit(EV_ABS, sensor->input_dev->evbit);\r
+                       /* x-axis acceleration */\r
+                       input_set_abs_params(sensor->input_dev, ABS_X, sensor->ops->range[0], sensor->ops->range[1], 0, 0); //2g full scale range\r
+                       /* y-axis acceleration */\r
+                       input_set_abs_params(sensor->input_dev, ABS_Y, sensor->ops->range[0], sensor->ops->range[1], 0, 0); //2g full scale range\r
+                       /* z-axis acceleration */\r
+                       input_set_abs_params(sensor->input_dev, ABS_Z, sensor->ops->range[0], sensor->ops->range[1], 0, 0); //2g full scale range\r
+                       break;          \r
+               case SENSOR_TYPE_COMPASS:       \r
+                       sensor->input_dev->name = "compass";            \r
+                       /* Setup input device */\r
+                       set_bit(EV_ABS, sensor->input_dev->evbit);\r
+                       /* yaw (0, 360) */\r
+                       input_set_abs_params(sensor->input_dev, ABS_RX, 0, 23040, 0, 0);\r
+                       /* pitch (-180, 180) */\r
+                       input_set_abs_params(sensor->input_dev, ABS_RY, -11520, 11520, 0, 0);\r
+                       /* roll (-90, 90) */\r
+                       input_set_abs_params(sensor->input_dev, ABS_RZ, -5760, 5760, 0, 0);\r
+                       /* x-axis acceleration (720 x 8G) */\r
+                       input_set_abs_params(sensor->input_dev, ABS_X, -5760, 5760, 0, 0);\r
+                       /* y-axis acceleration (720 x 8G) */\r
+                       input_set_abs_params(sensor->input_dev, ABS_Y, -5760, 5760, 0, 0);\r
+                       /* z-axis acceleration (720 x 8G) */\r
+                       input_set_abs_params(sensor->input_dev, ABS_Z, -5760, 5760, 0, 0);\r
+                       /* status of magnetic sensor */\r
+                       input_set_abs_params(sensor->input_dev, ABS_RUDDER, -32768, 3, 0, 0);\r
+                       /* status of acceleration sensor */\r
+                       input_set_abs_params(sensor->input_dev, ABS_WHEEL, -32768, 3, 0, 0);\r
+                       /* x-axis of raw magnetic vector (-4096, 4095) */\r
+                       input_set_abs_params(sensor->input_dev, ABS_HAT0X, -20480, 20479, 0, 0);\r
+                       /* y-axis of raw magnetic vector (-4096, 4095) */\r
+                       input_set_abs_params(sensor->input_dev, ABS_HAT0Y, -20480, 20479, 0, 0);\r
+                       /* z-axis of raw magnetic vector (-4096, 4095) */\r
+                       input_set_abs_params(sensor->input_dev, ABS_BRAKE, -20480, 20479, 0, 0);\r
+                       break;          \r
+               case SENSOR_TYPE_GYROSCOPE:\r
+                       sensor->input_dev->name = "gyro";\r
+                       /* x-axis acceleration */\r
+                       input_set_capability(sensor->input_dev, EV_REL, REL_RX);\r
+                       input_set_abs_params(sensor->input_dev, ABS_RX, sensor->ops->range[0], sensor->ops->range[1], 0, 0); \r
+                       /* y-axis acceleration */       \r
+                       input_set_capability(sensor->input_dev, EV_REL, REL_RY);\r
+                       input_set_abs_params(sensor->input_dev, ABS_RY, sensor->ops->range[0], sensor->ops->range[1], 0, 0); \r
+                       /* z-axis acceleration */\r
+                       input_set_capability(sensor->input_dev, EV_REL, REL_RZ);\r
+                       input_set_abs_params(sensor->input_dev, ABS_RZ, sensor->ops->range[0], sensor->ops->range[1], 0, 0); \r
+                       break;\r
+               case SENSOR_TYPE_LIGHT:\r
+                       sensor->input_dev->name = "lightsensor-level";\r
+                       set_bit(EV_ABS, sensor->input_dev->evbit);\r
+                       input_set_abs_params(sensor->input_dev, ABS_MISC, sensor->ops->range[0], sensor->ops->range[1], 0, 0);                  \r
+                       break;\r
+               case SENSOR_TYPE_PROXIMITY:\r
+                       sensor->input_dev->name = "proximity";  \r
+                       set_bit(EV_ABS, sensor->input_dev->evbit);\r
+                       input_set_abs_params(sensor->input_dev, ABS_DISTANCE, sensor->ops->range[0], sensor->ops->range[1], 0, 0);\r
+                       break;\r
+               case SENSOR_TYPE_TEMPERATURE:                           \r
+                       sensor->input_dev->name = "temperature";\r
+                       set_bit(EV_ABS, sensor->input_dev->evbit);              \r
+                       input_set_abs_params(sensor->input_dev, ABS_THROTTLE, sensor->ops->range[0], sensor->ops->range[1], 0, 0);\r
+                       break;\r
+               default:\r
+                       printk("%s:unknow sensor type=%d\n",__func__,type);\r
+                       break;\r
+\r
+       }\r
+       sensor->input_dev->dev.parent = &client->dev;\r
+
+       result = input_register_device(sensor->input_dev);\r
+       if (result) {\r
+               dev_err(&client->dev,\r
+                       "Unable to register input device %s\n", sensor->input_dev->name);\r
+               goto out_input_register_device_failed;\r
+       }\r
+\r
+       result = sensor_irq_init(sensor->client);\r
+       if (result) {\r
+               dev_err(&client->dev,\r
+                       "fail to init sensor irq,ret=%d\n",result);\r
+               goto out_input_register_device_failed;\r
+       }\r
+\r
+       \r
+       sensor->miscdev.parent = &client->dev;\r
+       result = sensor_misc_device_register(sensor, type);\r
+       if (result) {\r
+               dev_err(&client->dev,\r
+                       "fail to register misc device %s\n", sensor->miscdev.name);\r
+               goto out_misc_device_register_device_failed;\r
+       }\r
+       \r
+       g_sensor[type] = sensor;\r
+\r
+#ifdef CONFIG_HAS_EARLYSUSPEND\r
+       if((sensor->ops->suspend) && (sensor->ops->resume))\r
+       {\r
+               sensor->early_suspend.suspend = sensor_suspend;\r
+               sensor->early_suspend.resume = sensor_resume;\r
+               sensor->early_suspend.level = 0x02;\r
+               register_early_suspend(&sensor->early_suspend);\r
+       }\r
+#endif\r
+\r
+       printk("%s:initialized ok,sensor name:%s,type:%d\n",__func__,sensor->ops->name,type);\r
+\r
+       return result;\r
+       \r
+out_misc_device_register_device_failed:\r
+       input_unregister_device(sensor->input_dev);     \r
+out_input_register_device_failed:\r
+       input_free_device(sensor->input_dev);   \r
+out_free_memory:\r
+       kfree(sensor);\r
+out_no_free:\r
+       dev_err(&client->adapter->dev, "%s failed %d\n", __func__, result);\r
+       return result;\r
+\r
+}\r
+\r
+static void sensor_shut_down(struct i2c_client *client)\r
+{\r
+       struct sensor_private_data *sensor =\r
+           (struct sensor_private_data *) i2c_get_clientdata(client);\r
+       if((sensor->ops->suspend) && (sensor->ops->resume))             \r
+               unregister_early_suspend(&sensor->early_suspend);\r
+       DBG("%s:%s\n",__func__,sensor->i2c_id->name);\r
+}\r
+\r
+static int sensor_remove(struct i2c_client *client)\r
+{\r
+       struct sensor_private_data *sensor =\r
+           (struct sensor_private_data *) i2c_get_clientdata(client);\r
+       int result = 0;\r
+       \r
+       cancel_delayed_work_sync(&sensor->delaywork);\r
+       misc_deregister(&sensor->miscdev);\r
+       input_unregister_device(sensor->input_dev);     \r
+       input_free_device(sensor->input_dev);   \r
+       kfree(sensor);\r
+#ifdef CONFIG_HAS_EARLYSUSPEND\r
+       if((sensor->ops->suspend) && (sensor->ops->resume))\r
+       unregister_early_suspend(&sensor->early_suspend);\r
+#endif  \r
+       return result;\r
+}\r
+\r
+static const struct i2c_device_id sensor_id[] = {\r
+       /*gsensor*/\r
+       {"gsensor", ACCEL_ID_ALL},\r
+       {"gs_mma8452", ACCEL_ID_MMA845X},       \r
+       {"gs_kxtik", ACCEL_ID_KXTIK},\r
+       /*compass*/\r
+       {"compass", COMPASS_ID_ALL},\r
+       {"ak8975", COMPASS_ID_AK8975},\r
+       {"mmc314x", COMPASS_ID_MMC314X},\r
+       /*gyroscope*/\r
+       {"gyro", GYRO_ID_ALL},  \r
+       {"l3g4200d_gryo", GYRO_ID_L3G4200D},\r
+       {"k3g", GYRO_ID_K3G},\r
+       /*light sensor*/\r
+       {"lightsensor", LIGHT_ID_ALL},  \r
+       {"light_al3006", LIGHT_ID_AL3006},\r
+       /*proximity sensor*/\r
+       {"psensor", PROXIMITY_ID_ALL},\r
+       {"proximity_al3006", PROXIMITY_ID_AL3006},      \r
+       /*temperature*/\r
+       {"temperature", TEMPERATURE_ID_ALL},\r
+       {},\r
+};\r
+\r
+\r
+static struct i2c_driver sensor_driver = {\r
+       .probe = sensor_probe,\r
+       .remove = sensor_remove,\r
+       .shutdown = sensor_shut_down,\r
+       .id_table = sensor_id,\r
+       .driver = {\r
+                  .owner = THIS_MODULE,\r
+                  .name = "sensors",\r
+                  },\r
+};\r
+\r
+static int __init sensor_init(void)\r
+{\r
+       int res = i2c_add_driver(&sensor_driver);\r
+       pr_info("%s: Probe name %s\n", __func__, sensor_driver.driver.name);\r
+       if (res)\r
+               pr_err("%s failed\n", __func__);\r
+       return res;\r
+}\r
+\r
+static void __exit sensor_exit(void)\r
+{\r
+       pr_info("%s\n", __func__);\r
+       i2c_del_driver(&sensor_driver);\r
+}\r
+\r
+late_initcall(sensor_init);\r
+module_exit(sensor_exit);\r
+\r
+MODULE_AUTHOR("ROCKCHIP Corporation:lw@rock-chips.com");\r
+MODULE_DESCRIPTION("User space character device interface for sensors");\r
+MODULE_LICENSE("GPL");\r
+\r
diff --git a/drivers/input/sensors/sensor-i2c.c b/drivers/input/sensors/sensor-i2c.c
new file mode 100755 (executable)
index 0000000..29545cb
--- /dev/null
@@ -0,0 +1,234 @@
+/* drivers/input/sensors/sensor-i2c.c - sensor i2c handle\r
+ *\r
+ * Copyright (C) 2012-2015 ROCKCHIP.\r
+ * Author: luowei <lw@rock-chips.com>\r
+ *\r
+ * This software is licensed under the terms of the GNU General Public\r
+ * License version 2, as published by the Free Software Foundation, and\r
+ * may be copied, distributed, and modified under those terms.\r
+ *\r
+ * This program is distributed in the hope that it will be useful,\r
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+ * GNU General Public License for more details.\r
+ *\r
+ */\r
+#include <linux/interrupt.h>\r
+#include <linux/i2c.h>\r
+#include <linux/slab.h>\r
+#include <linux/irq.h>\r
+#include <linux/miscdevice.h>\r
+#include <linux/gpio.h>\r
+#include <asm/uaccess.h>\r
+#include <asm/atomic.h>\r
+#include <linux/delay.h>\r
+#include <linux/input.h>\r
+#include <linux/workqueue.h>\r
+#include <linux/freezer.h>\r
+#include <mach/gpio.h>\r
+#include <mach/board.h> \r
+#ifdef CONFIG_HAS_EARLYSUSPEND\r
+#include <linux/earlysuspend.h>\r
+#endif\r
+#include <linux/sensor-dev.h>\r
+\r
+#define SENSOR_I2C_RATE 200*1000\r
+\r
+#if 0\r
+#define SENSOR_DEBUG_TYPE SENSOR_TYPE_COMPASS\r
+#define DBG(x...) if(sensor->pdata->type == SENSOR_DEBUG_TYPE) printk(x)\r
+#else\r
+#define DBG(x...)\r
+#endif\r
+\r
+static int sensor_i2c_write(struct i2c_adapter *i2c_adap,\r
+                           unsigned char address,\r
+                           unsigned int len, unsigned char const *data)\r
+{\r
+       struct i2c_msg msgs[1];\r
+       int res;\r
+\r
+       if (!data || !i2c_adap) {\r
+               printk("%s:line=%d,error\n",__func__,__LINE__);\r
+               return -EINVAL;\r
+       }\r
+\r
+       msgs[0].addr = address;\r
+       msgs[0].flags = 0;      /* write */\r
+       msgs[0].buf = (unsigned char *)data;\r
+       msgs[0].len = len;\r
+       msgs[0].scl_rate = SENSOR_I2C_RATE;\r
+\r
+       res = i2c_transfer(i2c_adap, msgs, 1);\r
+       if (res == 1)\r
+               return 0;\r
+       else if(res == 0)\r
+               return -EBUSY;\r
+       else\r
+               return res;\r
+\r
+}\r
+\r
+static int senosr_i2c_read(struct i2c_adapter *i2c_adap,\r
+                          unsigned char address, unsigned char reg,\r
+                          unsigned int len, unsigned char *data)\r
+{\r
+       struct i2c_msg msgs[2];\r
+       int res;\r
+\r
+       if (!data || !i2c_adap) {\r
+               printk("%s:line=%d,error\n",__func__,__LINE__);\r
+               return -EINVAL;\r
+       }\r
+\r
+       msgs[0].addr = address;\r
+       msgs[0].flags = 0;      /* write */\r
+       msgs[0].buf = &reg;\r
+       msgs[0].len = 1;\r
+       msgs[0].scl_rate = SENSOR_I2C_RATE;\r
+       \r
+       msgs[1].addr = address;\r
+       msgs[1].flags = I2C_M_RD;\r
+       msgs[1].buf = data;\r
+       msgs[1].len = len;\r
+       msgs[1].scl_rate = SENSOR_I2C_RATE;     \r
+\r
+       res = i2c_transfer(i2c_adap, msgs, 2);\r
+       if (res == 2)\r
+               return 0;\r
+       else if(res == 0)\r
+               return -EBUSY;\r
+       else\r
+               return res;\r
+\r
+}\r
+\r
+\r
+int sensor_rx_data(struct i2c_client *client, char *rxData, int length)\r
+{\r
+#ifdef SENSOR_DEBUG_TYPE\r
+       struct sensor_private_data* sensor = \r
+               (struct sensor_private_data *)i2c_get_clientdata(client);\r
+       int i = 0;\r
+#endif\r
+       int ret = 0;\r
+       char reg = rxData[0];\r
+       ret = senosr_i2c_read(client->adapter, client->addr, reg, length, rxData);\r
+       \r
+#ifdef SENSOR_DEBUG_TYPE\r
+       DBG("addr=0x%x,len=%d,rxdata:",reg,length);\r
+       for(i=0; i<length; i++)\r
+               DBG("0x%x,",rxData[i]);\r
+       DBG("\n");\r
+#endif \r
+       return ret;\r
+}\r
+EXPORT_SYMBOL(sensor_rx_data);\r
+\r
+int sensor_tx_data(struct i2c_client *client, char *txData, int length)\r
+{\r
+#ifdef SENSOR_DEBUG_TYPE       \r
+       struct sensor_private_data* sensor = \r
+               (struct sensor_private_data *)i2c_get_clientdata(client);\r
+       int i = 0;\r
+#endif\r
+       int ret = 0;\r
+#ifdef SENSOR_DEBUG_TYPE       \r
+       DBG("addr=0x%x,len=%d,txdata:",txData[0],length);\r
+       for(i=1; i<length; i++)\r
+               DBG("0x%x,",txData[i]);\r
+       DBG("\n");\r
+#endif\r
+       ret = sensor_i2c_write(client->adapter, client->addr, length, txData);\r
+       return ret;\r
+\r
+}\r
+EXPORT_SYMBOL(sensor_tx_data);\r
+\r
+int sensor_write_reg(struct i2c_client *client, int addr, int value)\r
+{\r
+       char buffer[2];\r
+       int ret = 0;\r
+       struct sensor_private_data* sensor = \r
+               (struct sensor_private_data *)i2c_get_clientdata(client);\r
+       \r
+       mutex_lock(&sensor->i2c_mutex); \r
+       buffer[0] = addr;\r
+       buffer[1] = value;\r
+       ret = sensor_tx_data(client, &buffer[0], 2);    \r
+       mutex_unlock(&sensor->i2c_mutex);       \r
+       return ret;\r
+}\r
+EXPORT_SYMBOL(sensor_write_reg);\r
+\r
+int sensor_read_reg(struct i2c_client *client, int addr)\r
+{\r
+       char tmp[1] = {0};\r
+       int ret = 0;    \r
+       struct sensor_private_data* sensor = \r
+               (struct sensor_private_data *)i2c_get_clientdata(client);\r
+       \r
+       mutex_lock(&sensor->i2c_mutex); \r
+       tmp[0] = addr;\r
+       ret = sensor_rx_data(client, tmp, 1);\r
+       mutex_unlock(&sensor->i2c_mutex);\r
+       \r
+       return tmp[0];\r
+}\r
+\r
+EXPORT_SYMBOL(sensor_read_reg);\r
+\r
+\r
+int sensor_tx_data_normal(struct i2c_client *client, char *buf, int num)\r
+{\r
+       int ret = 0;\r
+       ret = i2c_master_normal_send(client, buf, num, SENSOR_I2C_RATE);\r
+       \r
+       return (ret == num) ? 0 : ret;\r
+}\r
+EXPORT_SYMBOL(sensor_tx_data_normal);\r
+\r
+\r
+int sensor_rx_data_normal(struct i2c_client *client, char *buf, int num)\r
+{\r
+       int ret = 0;\r
+       ret = i2c_master_normal_recv(client, buf, num, SENSOR_I2C_RATE);\r
+       \r
+       return (ret == num) ? 0 : ret;\r
+}\r
+\r
+EXPORT_SYMBOL(sensor_rx_data_normal);\r
+\r
+\r
+int sensor_write_reg_normal(struct i2c_client *client, char value)\r
+{\r
+       char buffer[2];\r
+       int ret = 0;\r
+       struct sensor_private_data* sensor = \r
+               (struct sensor_private_data *)i2c_get_clientdata(client);\r
+       \r
+       mutex_lock(&sensor->i2c_mutex); \r
+       buffer[0] = value;\r
+       ret = sensor_tx_data_normal(client, &buffer[0], 1);     \r
+       mutex_unlock(&sensor->i2c_mutex);       \r
+       return ret;\r
+}\r
+EXPORT_SYMBOL(sensor_write_reg_normal);\r
+\r
+int sensor_read_reg_normal(struct i2c_client *client)\r
+{\r
+       char tmp[0];\r
+       int ret = 0;    \r
+       struct sensor_private_data* sensor = \r
+               (struct sensor_private_data *)i2c_get_clientdata(client);\r
+       \r
+       mutex_lock(&sensor->i2c_mutex); \r
+       ret = sensor_rx_data_normal(client, tmp, 1);\r
+       mutex_unlock(&sensor->i2c_mutex);\r
+       \r
+       return tmp[0];\r
+}\r
+\r
+EXPORT_SYMBOL(sensor_read_reg_normal);\r
+\r
+\r
diff --git a/drivers/input/sensors/temperature/Kconfig b/drivers/input/sensors/temperature/Kconfig
new file mode 100755 (executable)
index 0000000..e69de29
diff --git a/drivers/input/sensors/temperature/Makefile b/drivers/input/sensors/temperature/Makefile
new file mode 100755 (executable)
index 0000000..e69de29
old mode 100644 (file)
new mode 100755 (executable)
index 6a7c432..e14fe06
@@ -6,17 +6,21 @@
 
 #include <linux/ioctl.h>
 
+#define AKM8975_I2C_NAME "ak8975"
+
 /*! \name AK8975 operation mode
  \anchor AK8975_Mode
  Defines an operation mode of the AK8975.*/
 /*! @{*/
-#define AK8975_MODE_SNG_MEASURE   0x01
-#define        AK8975_MODE_SELF_TEST     0x08
-#define        AK8975_MODE_FUSE_ACCESS   0x0F
-#define        AK8975_MODE_POWER_DOWN    0x00
+#define AK8975_MODE_SNG_MEASURE        0x01
+#define        AK8975_MODE_SELF_TEST   0x08
+#define        AK8975_MODE_FUSE_ACCESS 0x0F
+#define        AK8975_MODE_POWERDOWN   0x00
 /*! @}*/
 
-#define RBUFF_SIZE             8       /* Rx buffer size */
+#define SENSOR_DATA_SIZE               8       /* Rx buffer size, i.e from ST1 to ST2 */
+#define RWBUF_SIZE                             16      /* Read/Write buffer size.*/
+
 
 /*! \name AK8975 register address
 \anchor AK8975_REG
@@ -52,36 +56,34 @@ Defines a read-only address of the fuse ROM of the AK8975.*/
 #define AKMIO                   0xA1
 
 /* IOCTLs for AKM library */
-#define ECS_IOCTL_WRITE                 _IOW(AKMIO, 0x02, char[5])
-#define ECS_IOCTL_READ                  _IOWR(AKMIO, 0x03, char[5])
-#define ECS_IOCTL_GETDATA               _IOR(AKMIO, 0x08, char[RBUFF_SIZE])
-#define ECS_IOCTL_SET_YPR               _IOW(AKMIO, 0x0C, short[12])
-#define ECS_IOCTL_GET_OPEN_STATUS       _IOR(AKMIO, 0x0D, int)
-#define ECS_IOCTL_GET_CLOSE_STATUS      _IOR(AKMIO, 0x0E, int)
+#define ECS_IOCTL_WRITE                 _IOW(AKMIO, 0x01, char*)
+#define ECS_IOCTL_READ                  _IOWR(AKMIO, 0x02, char*)
+#define ECS_IOCTL_RESET                _IO(AKMIO, 0x03) /* NOT used in AK8975 */
+#define ECS_IOCTL_SET_MODE              _IOW(AKMIO, 0x04, short)
+#define ECS_IOCTL_GETDATA               _IOR(AKMIO, 0x05, char[SENSOR_DATA_SIZE])
+#define ECS_IOCTL_SET_YPR               _IOW(AKMIO, 0x06, short[12])
+#define ECS_IOCTL_GET_OPEN_STATUS       _IOR(AKMIO, 0x07, int)
+#define ECS_IOCTL_GET_CLOSE_STATUS      _IOR(AKMIO, 0x08, int)
 #define ECS_IOCTL_GET_DELAY             _IOR(AKMIO, 0x30, short)
+#define ECS_IOCTL_GET_PROJECT_NAME      _IOR(AKMIO, 0x0D, char[64])
+#define ECS_IOCTL_GET_MATRIX            _IOR(AKMIO, 0x0E, short [4][3][3])
+#define ECS_IOCTL_GET_PLATFORM_DATA     _IOR(AKMIO, 0x0E, struct akm8975_platform_data)
+
 
 /* IOCTLs for APPs */
+#define ECS_IOCTL_APP_SET_MODE         _IOW(AKMIO, 0x10, short)
 #define ECS_IOCTL_APP_SET_MFLAG                _IOW(AKMIO, 0x11, short)
 #define ECS_IOCTL_APP_GET_MFLAG                _IOW(AKMIO, 0x12, short)
 #define ECS_IOCTL_APP_SET_AFLAG                _IOW(AKMIO, 0x13, short)
 #define ECS_IOCTL_APP_GET_AFLAG                _IOR(AKMIO, 0x14, short)
+#define ECS_IOCTL_APP_SET_TFLAG                _IOR(AKMIO, 0x15, short)/* NOT use */
+#define ECS_IOCTL_APP_GET_TFLAG                _IOR(AKMIO, 0x16, short)/* NOT use */
+#define ECS_IOCTL_APP_RESET_PEDOMETER   _IO(AKMIO, 0x17)       /* NOT use */
 #define ECS_IOCTL_APP_SET_DELAY                _IOW(AKMIO, 0x18, short)
 #define ECS_IOCTL_APP_GET_DELAY                ECS_IOCTL_GET_DELAY
-/* Set raw magnetic vector flag */
 #define ECS_IOCTL_APP_SET_MVFLAG       _IOW(AKMIO, 0x19, short)
-/* Get raw magnetic vector flag */
 #define ECS_IOCTL_APP_GET_MVFLAG       _IOR(AKMIO, 0x1A, short)
-#define ECS_IOCTL_APP_SET_TFLAG         _IOR(AKMIO, 0x15, short)
-
-
-struct akm8975_platform_data {
-       int intr;
 
-       int (*init)(void);
-       void (*exit)(void);
-       int (*power_on)(void);
-       int (*power_off)(void);
-};
 
 #endif
 
diff --git a/include/linux/kxtik.h b/include/linux/kxtik.h
new file mode 100755 (executable)
index 0000000..28ef3c7
--- /dev/null
@@ -0,0 +1,77 @@
+#define KXTIK_DEVID            0x05    //chip id\r
+#define KXTIK_RANGE    2000000\r
+\r
+#define KXTIK_XOUT_HPF_L                (0x00) /* 0000 0000 */\r
+#define KXTIK_XOUT_HPF_H                (0x01) /* 0000 0001 */\r
+#define KXTIK_YOUT_HPF_L                (0x02) /* 0000 0010 */\r
+#define KXTIK_YOUT_HPF_H                (0x03) /* 0000 0011 */\r
+#define KXTIK_ZOUT_HPF_L                (0x04) /* 0001 0100 */\r
+#define KXTIK_ZOUT_HPF_H                (0x05) /* 0001 0101 */\r
+#define KXTIK_XOUT_L                    (0x06) /* 0000 0110 */\r
+#define KXTIK_XOUT_H                    (0x07) /* 0000 0111 */\r
+#define KXTIK_YOUT_L                    (0x08) /* 0000 1000 */\r
+#define KXTIK_YOUT_H                    (0x09) /* 0000 1001 */\r
+#define KXTIK_ZOUT_L                    (0x0A) /* 0001 1010 */\r
+#define KXTIK_ZOUT_H                    (0x0B) /* 0001 1011 */\r
+#define KXTIK_ST_RESP                   (0x0C) /* 0000 1100 */\r
+#define KXTIK_WHO_AM_I                  (0x0F) /* 0000 1111 */\r
+#define KXTIK_TILT_POS_CUR              (0x10) /* 0001 0000 */\r
+#define KXTIK_TILT_POS_PRE              (0x11) /* 0001 0001 */\r
+#define KXTIK_INT_SRC_REG1              (0x15) /* 0001 0101 */\r
+#define KXTIK_INT_SRC_REG2              (0x16) /* 0001 0110 */\r
+#define KXTIK_STATUS_REG                (0x18) /* 0001 1000 */\r
+#define KXTIK_INT_REL                   (0x1A) /* 0001 1010 */\r
+#define KXTIK_CTRL_REG1                 (0x1B) /* 0001 1011 */\r
+#define KXTIK_CTRL_REG2                 (0x1C) /* 0001 1100 */\r
+#define KXTIK_CTRL_REG3                 (0x1D) /* 0001 1101 */\r
+#define KXTIK_INT_CTRL_REG1             (0x1E) /* 0001 1110 */\r
+#define KXTIK_INT_CTRL_REG2             (0x1F) /* 0001 1111 */\r
+#define KXTIK_INT_CTRL_REG3             (0x20) /* 0010 0000 */\r
+#define KXTIK_DATA_CTRL_REG             (0x21) /* 0010 0001 */\r
+#define KXTIK_TILT_TIMER                (0x28) /* 0010 1000 */\r
+#define KXTIK_WUF_TIMER                 (0x29) /* 0010 1001 */\r
+#define KXTIK_TDT_TIMER                 (0x2B) /* 0010 1011 */\r
+#define KXTIK_TDT_H_THRESH              (0x2C) /* 0010 1100 */\r
+#define KXTIK_TDT_L_THRESH              (0x2D) /* 0010 1101 */\r
+#define KXTIK_TDT_TAP_TIMER             (0x2E) /* 0010 1110 */\r
+#define KXTIK_TDT_TOTAL_TIMER           (0x2F) /* 0010 1111 */\r
+#define KXTIK_TDT_LATENCY_TIMER         (0x30) /* 0011 0000 */\r
+#define KXTIK_TDT_WINDOW_TIMER          (0x31) /* 0011 0001 */\r
+#define KXTIK_WUF_THRESH                (0x5A) /* 0101 1010 */\r
+#define KXTIK_TILT_ANGLE                (0x5C) /* 0101 1100 */\r
+#define KXTIK_HYST_SET                  (0x5F) /* 0101 1111 */\r
+\r
+/* CONTROL REGISTER 1 BITS */\r
+#define KXTIK_DISABLE                  0x7F\r
+#define KXTIK_ENABLE                   (1 << 7)\r
+/* INPUT_ABS CONSTANTS */\r
+#define FUZZ                   3\r
+#define FLAT                   3\r
+/* RESUME STATE INDICES */\r
+#define RES_DATA_CTRL          0\r
+#define RES_CTRL_REG1          1\r
+#define RES_INT_CTRL1          2\r
+#define RESUME_ENTRIES         3\r
+\r
+/* CTRL_REG1: set resolution, g-range, data ready enable */\r
+/* Output resolution: 8-bit valid or 12-bit valid */\r
+#define KXTIK_RES_8BIT         0\r
+#define KXTIK_RES_12BIT                (1 << 6)\r
+/* Output g-range: +/-2g, 4g, or 8g */\r
+#define KXTIK_G_2G             0\r
+#define KXTIK_G_4G             (1 << 3)\r
+#define KXTIK_G_8G             (1 << 4)\r
+\r
+/* DATA_CTRL_REG: controls the output data rate of the part */\r
+#define KXTIK_ODR12_5F         0\r
+#define KXTIK_ODR25F                   1\r
+#define KXTIK_ODR50F                   2\r
+#define KXTIK_ODR100F                  3\r
+#define KXTIK_ODR200F                  4\r
+#define KXTIK_ODR400F                  5\r
+#define KXTIK_ODR800F                  6\r
+\r
+/* kxtik */\r
+#define KXTIK_PRECISION       12\r
+#define KXTIK_BOUNDARY        (0x1 << (KXTIK_PRECISION - 1))\r
+#define KXTIK_GRAVITY_STEP    KXTIK_RANGE / KXTIK_BOUNDARY\r
index 03a5ff018665256d34f9cd1a5d4c3707641a492c..c040b5121fe40b91495ba4a79c6d050c19ca3f1f 100755 (executable)
 #define L3G4200D_FS_500DPS     0x10
 #define L3G4200D_FS_2000DPS    0x30
 
-#define PM_OFF         0x00
-#define PM_NORMAL      0x08
-#define ENABLE_ALL_AXES        0x07
+#define PM_OFF                         0x00
+#define PM_NORMAL                      0x08
+#define ENABLE_ALL_AXES                0x07
+
+/* l3g4200d gyroscope registers */
+#define GYRO_WHO_AM_I          0x0F
+#define GYRO_CTRL_REG1         0x20    /* power control reg */
+#define GYRO_CTRL_REG2         0x21    /* power control reg */
+#define GYRO_CTRL_REG3         0x22    /* power control reg */
+#define GYRO_CTRL_REG4         0x23    /* interrupt control reg */
+#define GYRO_CTRL_REG5         0x24    /* interrupt control reg */
+#define GYRO_DATA_REG          0x28
+#define GYRO_INT_SRC           0x31
+
+
+
 
 /*status*/
-#define L3G4200D_SUSPEND           2
+#define L3G4200D_SUSPEND               2
 #define L3G4200D_OPEN           1
 #define L3G4200D_CLOSE          0
 
diff --git a/include/linux/sensor-dev.h b/include/linux/sensor-dev.h
new file mode 100755 (executable)
index 0000000..c087b1b
--- /dev/null
@@ -0,0 +1,194 @@
+/* include/linux/sensor-dev.h - sensor header file\r
+ *\r
+ * Copyright (C) 2012-2015 ROCKCHIP.\r
+ * Author: luowei <lw@rock-chips.com>\r
+ *\r
+ * This software is licensed under the terms of the GNU General Public\r
+ * License version 2, as published by the Free Software Foundation, and\r
+ * may be copied, distributed, and modified under those terms.\r
+ *\r
+ * This program is distributed in the hope that it will be useful,\r
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+ * GNU General Public License for more details.\r
+ *\r
+ */\r
+\r
+#include <linux/miscdevice.h>\r
+#ifdef CONFIG_HAS_EARLYSUSPEND\r
+#include <linux/earlysuspend.h>\r
+#endif\r
+\r
+\r
+#define SENSOR_ON              1\r
+#define SENSOR_OFF             0\r
+#define SENSOR_UNKNOW_DATA     -1\r
+\r
+enum sensor_type {\r
+       SENSOR_TYPE_NULL,\r
+       SENSOR_TYPE_ACCEL,\r
+       SENSOR_TYPE_COMPASS,    \r
+       SENSOR_TYPE_GYROSCOPE,  \r
+       SENSOR_TYPE_LIGHT,      \r
+       SENSOR_TYPE_PROXIMITY,\r
+       SENSOR_TYPE_TEMPERATURE,        \r
+       //SENSOR_TYPE_PRESSURE,\r
+       SENSOR_NUM_TYPES\r
+};\r
+\r
+enum sensor_id {\r
+       ID_INVALID = 0,\r
+               \r
+       ACCEL_ID_ALL,\r
+       ACCEL_ID_LIS331,\r
+       ACCEL_ID_LSM303DLX,\r
+       ACCEL_ID_LIS3DH,\r
+       ACCEL_ID_KXSD9,\r
+       ACCEL_ID_KXTF9,\r
+       ACCEL_ID_KXTIK,\r
+       ACCEL_ID_BMA150,\r
+       ACCEL_ID_BMA222,\r
+       ACCEL_ID_BMA250,\r
+       ACCEL_ID_ADXL34X,\r
+       ACCEL_ID_MMA8450,\r
+       ACCEL_ID_MMA845X,\r
+       ACCEL_ID_MPU6050,\r
+\r
+       COMPASS_ID_ALL,\r
+       COMPASS_ID_AK8975,\r
+       COMPASS_ID_AK8972,\r
+       COMPASS_ID_AMI30X,\r
+       COMPASS_ID_AMI306,\r
+       COMPASS_ID_YAS529,\r
+       COMPASS_ID_YAS530,\r
+       COMPASS_ID_HMC5883,\r
+       COMPASS_ID_LSM303DLH,\r
+       COMPASS_ID_LSM303DLM,\r
+       COMPASS_ID_MMC314X,\r
+       COMPASS_ID_HSCDTD002B,\r
+       COMPASS_ID_HSCDTD004A,\r
+\r
+       GYRO_ID_ALL,\r
+       GYRO_ID_L3G4200D,\r
+       GYRO_ID_K3G,\r
+\r
+       LIGHT_ID_ALL,\r
+       LIGHT_ID_CM3217,\r
+       LIGHT_ID_AL3006,\r
+       LIGHT_ID_STK3171,\r
+       \r
+       PROXIMITY_ID_ALL,\r
+       PROXIMITY_ID_AL3006,\r
+       PROXIMITY_ID_STK3171,\r
+       TEMPERATURE_ID_ALL,\r
+\r
+       PRESSURE_ID_ALL,\r
+       PRESSURE_ID_BMA085,\r
+};\r
+\r
+\r
+struct sensor_axis {\r
+       int x;\r
+       int y;\r
+       int z;\r
+};\r
+\r
+struct sensor_operate {\r
+       char *name;\r
+       int type;\r
+       int     id_i2c;\r
+       int     range[2];\r
+       int read_reg;\r
+       int read_len;\r
+       int id_reg;\r
+       int id_data;\r
+       int precision;\r
+       int ctrl_reg;\r
+       int ctrl_data;\r
+       int int_ctrl_reg;\r
+       int     int_status_reg;\r
+       int trig;       //intterupt trigger\r
+       int (*active)(struct i2c_client *client, int enable, int rate); \r
+       int (*init)(struct i2c_client *client); \r
+       int (*report)(struct i2c_client *client);\r
+       int (*suspend)(struct i2c_client *client);\r
+       int (*resume)(struct i2c_client *client);\r
+       struct miscdevice *misc_dev;\r
+\r
+};\r
+\r
+\r
+/* Platform data for the sensor */\r
+struct sensor_private_data {\r
+       int type;\r
+       struct i2c_client *client;      \r
+       struct input_dev *input_dev;\r
+       struct work_struct work;\r
+       struct delayed_work delaywork;  /*report second event*/\r
+       struct sensor_axis axis;\r
+       char sensor_data[40];           //max support40 bytes data\r
+       atomic_t data_ready;\r
+       wait_queue_head_t data_ready_wq;                \r
+       struct mutex data_mutex;\r
+       struct mutex operation_mutex;   \r
+       struct mutex sensor_mutex;\r
+       struct mutex i2c_mutex;\r
+       int status_cur;\r
+       int start_count;\r
+       int devid;\r
+       struct i2c_device_id *i2c_id;\r
+       struct sensor_platform_data *pdata;\r
+       struct sensor_operate *ops; \r
+       struct file_operations fops;\r
+       struct miscdevice miscdev;\r
+#ifdef CONFIG_HAS_EARLYSUSPEND\r
+       struct  early_suspend early_suspend;\r
+#endif\r
+};\r
+\r
+\r
+extern int sensor_register_slave(int type,struct i2c_client *client,\r
+                       struct sensor_platform_data *slave_pdata,\r
+                       struct sensor_operate *(*get_sensor_ops)(void));\r
+\r
+\r
+extern int sensor_unregister_slave(int type,struct i2c_client *client,\r
+                       struct sensor_platform_data *slave_pdata,\r
+                       struct sensor_operate *(*get_sensor_ops)(void));\r
+\r
+\r
+#define GSENSOR_IO                             0xA1\r
+#define GBUFF_SIZE                             12      /* Rx buffer size */\r
+\r
+/* IOCTLs for MMA8452 library */\r
+#define GSENSOR_IOCTL_INIT                  _IO(GSENSOR_IO, 0x01)\r
+#define GSENSOR_IOCTL_RESET                    _IO(GSENSOR_IO, 0x04)\r
+#define GSENSOR_IOCTL_CLOSE                            _IO(GSENSOR_IO, 0x02)\r
+#define GSENSOR_IOCTL_START                        _IO(GSENSOR_IO, 0x03)\r
+#define GSENSOR_IOCTL_GETDATA               _IOR(GSENSOR_IO, 0x08, char[GBUFF_SIZE+1])\r
+/* IOCTLs for APPs */\r
+#define GSENSOR_IOCTL_APP_SET_RATE                     _IOW(GSENSOR_IO, 0x10, char)\r
+\r
+\r
+#define LIGHTSENSOR_IOCTL_MAGIC 'l'\r
+#define LIGHTSENSOR_IOCTL_GET_ENABLED          _IOR(LIGHTSENSOR_IOCTL_MAGIC, 1, int *) \r
+#define LIGHTSENSOR_IOCTL_ENABLE                       _IOW(LIGHTSENSOR_IOCTL_MAGIC, 2, int *) \r
+#define LIGHTSENSOR_IOCTL_DISABLE                      _IOW(LIGHTSENSOR_IOCTL_MAGIC, 3, int *)\r
+\r
+#define PSENSOR_IOCTL_MAGIC 'c'\r
+#define PSENSOR_IOCTL_GET_ENABLED                      _IOR(PSENSOR_IOCTL_MAGIC, 1, int *)\r
+#define PSENSOR_IOCTL_ENABLE                           _IOW(PSENSOR_IOCTL_MAGIC, 2, int *)\r
+#define PSENSOR_IOCTL_DISABLE                  _IOW(PSENSOR_IOCTL_MAGIC, 3, int *)\r
+\r
+\r
+\r
+\r
+extern int sensor_rx_data(struct i2c_client *client, char *rxData, int length);\r
+extern int sensor_tx_data(struct i2c_client *client, char *txData, int length);\r
+extern int sensor_write_reg(struct i2c_client *client, int addr, int value);\r
+extern int sensor_read_reg(struct i2c_client *client, int addr);\r
+extern int sensor_tx_data_normal(struct i2c_client *client, char *buf, int num);\r
+extern int sensor_rx_data_normal(struct i2c_client *client, char *buf, int num);\r
+extern int sensor_write_reg_normal(struct i2c_client *client, char value);\r
+extern int sensor_read_reg_normal(struct i2c_client *client);\r
+\r