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;
source "drivers/input/lightsensor/Kconfig"
+source "drivers/input/sensors/Kconfig"
endif
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
--- /dev/null
+#
+# 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
--- /dev/null
+# 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
--- /dev/null
+#
+# 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
+
--- /dev/null
+\r
+obj-$(CONFIG_GS_KXTIK) += kxtik.o\r
+obj-$(CONFIG_GS_MMA8452) += mma8452.o
\ No newline at end of file
--- /dev/null
+/* 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
--- /dev/null
+/* 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
--- /dev/null
+#
+# 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
+
--- /dev/null
+#
+# 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
--- /dev/null
+/* 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
--- /dev/null
+#
+# 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
--- /dev/null
+# gyroscope drivers
+
+obj-$(CONFIG_GYRO_SENSOR_K3G) += k3g.o
+obj-$(CONFIG_GYRO_L3G4200D) += l3g4200d.o
\ No newline at end of file
--- /dev/null
+/* 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
--- /dev/null
+#
+# 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
+
--- /dev/null
+# 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
--- /dev/null
+/* 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
--- /dev/null
+/* 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
--- /dev/null
+/* 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
--- /dev/null
+#
+# 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
+
--- /dev/null
+# gsensor drivers
+
+obj-$(CONFIG_PS_AL3006) += ps_al3006.o
+obj-$(CONFIG_PS_STK3171) += ps_stk3171.o
\ No newline at end of file
--- /dev/null
+/* 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
--- /dev/null
+/* 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
--- /dev/null
+/* 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
--- /dev/null
+/* 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 = ®\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
#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
#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
--- /dev/null
+#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
#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
--- /dev/null
+/* 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