input: sensors: fromdos and remove trailing whitespace
[firefly-linux-kernel-4.4.55.git] / drivers / input / sensors / accel / dmard10.c
index f695818c3009ae176f6b7dc59eb31d51968dd2aa..db1545aa462cf63f9b7d411f120caaf3c7b35dc2 100755 (executable)
-/* drivers/input/sensors/access/dmard10.c\r
- *\r
- * Copyright (C) 2012-2015 ROCKCHIP.\r
- * Author: guoyi <gy@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 <linux/of_gpio.h>\r
-#ifdef CONFIG_HAS_EARLYSUSPEND\r
-#include <linux/earlysuspend.h>\r
-#endif\r
-#include <linux/sensor-dev.h>\r
-\r
-/* Default register settings */\r
-#define RBUFF_SIZE             12      /* Rx buffer size */\r
-\r
-#define REG_ACTR                               0x00\r
-#define REG_WDAL                               0x01\r
-#define REG_TAPNS                              0x0f\r
-#define REG_MISC2                              0x1f\r
-#define REG_AFEM                               0x0c\r
-#define REG_CKSEL                              0x0d\r
-#define REG_INTC                               0x0e\r
-#define REG_STADR                              0x12\r
-#define REG_STAINT                             0x1C\r
-#define REG_PD                                 0x21\r
-#define REG_TCGYZ                              0x26\r
-#define REG_X_OUT                              0x41\r
-\r
-#define MODE_Off                               0x00\r
-#define MODE_ResetAtOff                        0x01\r
-#define MODE_Standby                   0x02\r
-#define MODE_ResetAtStandby            0x03\r
-#define MODE_Active                            0x06\r
-#define MODE_Trigger                   0x0a\r
-#define MODE_ReadOTP                   0x12\r
-#define MODE_WriteOTP                  0x22\r
-#define MODE_WriteOTPBuf               0x42\r
-#define MODE_ResetDataPath             0x82\r
-\r
-#define VALUE_STADR                                    0x55\r
-#define VALUE_STAINT                           0xAA\r
-#define VALUE_AFEM_AFEN_Normal         0x8f// AFEN set 1 , ATM[2:0]=b'000(normal),EN_Z/Y/X/T=1\r
-#define VALUE_AFEM_Normal                      0x0f// AFEN set 0 , ATM[2:0]=b'000(normal),EN_Z/Y/X/T=1\r
-#define VALUE_INTC                                     0x00// INTC[6:5]=b'00 \r
-#define VALUE_INTC_Interrupt_En                0x20// INTC[6:5]=b'01 (Data ready interrupt enable, active high at INT0)\r
-#define VALUE_CKSEL_ODR_0_204          0x04// ODR[3:0]=b'0000 (0.78125Hz), CCK[3:0]=b'0100 (204.8kHZ)\r
-#define VALUE_CKSEL_ODR_1_204          0x14// ODR[3:0]=b'0001 (1.5625Hz), CCK[3:0]=b'0100 (204.8kHZ)\r
-#define VALUE_CKSEL_ODR_3_204          0x24// ODR[3:0]=b'0010 (3.125Hz), CCK[3:0]=b'0100 (204.8kHZ)\r
-#define VALUE_CKSEL_ODR_6_204          0x34// ODR[3:0]=b'0011 (6.25Hz), CCK[3:0]=b'0100 (204.8kHZ)\r
-#define VALUE_CKSEL_ODR_12_204         0x44// ODR[3:0]=b'0100 (12.5Hz), CCK[3:0]=b'0100 (204.8kHZ)\r
-#define VALUE_CKSEL_ODR_25_204         0x54// ODR[3:0]=b'0101 (25Hz), CCK[3:0]=b'0100 (204.8kHZ)\r
-#define VALUE_CKSEL_ODR_50_204         0x64// ODR[3:0]=b'0110 (50Hz), CCK[3:0]=b'0100 (204.8kHZ)\r
-#define VALUE_CKSEL_ODR_100_204                0x74// ODR[3:0]=b'0111 (100Hz), CCK[3:0]=b'0100 (204.8kHZ)\r
-\r
-#define VALUE_TAPNS_NoFilter   0x00    // TAP1/TAP2    NO FILTER\r
-#define VALUE_TAPNS_Ave_2              0x11    // TAP1/TAP2    Average 2\r
-#define VALUE_TAPNS_Ave_4              0x22    // TAP1/TAP2    Average 4\r
-#define VALUE_TAPNS_Ave_8              0x33    // TAP1/TAP2    Average 8\r
-#define VALUE_TAPNS_Ave_16             0x44    // TAP1/TAP2    Average 16\r
-#define VALUE_TAPNS_Ave_32             0x55    // TAP1/TAP2    Average 32\r
-#define VALUE_MISC2_OSCA_EN            0x08\r
-#define VALUE_PD_RST                   0x52\r
-\r
-\r
-//#define DMARD10_REG_INTSU        0x47\r
-//#define DMARD10_REG_MODE        0x44\r
-//#define DMARD10_REG_SR               0x44\r
-\r
-\r
-#define DMARD10_REG_DS      0X49\r
-#define DMARD10_REG_ID       0X0F\r
-#define DMARD10_REG_IT       0X4D\r
-#define DMARD10_REG_INTSRC1_C       0X4A\r
-#define DMARD10_REG_INTSRC1_S       0X4B\r
-#define MMAIO                          0xA1\r
-\r
-// IOCTLs for DMARD10 library \r
-#define ECS_IOCTL_INIT                  _IO(MMAIO, 0x01)\r
-#define ECS_IOCTL_RESET                _IO(MMAIO, 0x04)\r
-#define ECS_IOCTL_CLOSE                        _IO(MMAIO, 0x02)\r
-#define ECS_IOCTL_START                        _IO(MMAIO, 0x03)\r
-#define ECS_IOCTL_GETDATA               _IOR(MMAIO, 0x08, char[RBUFF_SIZE+1])\r
-#define SENSOR_CALIBRATION             _IOWR(MMAIO, 0x05 , int[SENSOR_DATA_SIZE])\r
-        \r
-// IOCTLs for APPs \r
-#define ECS_IOCTL_APP_SET_RATE         _IOW(MMAIO, 0x10, char)\r
-\r
- //rate\r
-#define DMARD10_RANGE                                          2000000\r
-\r
-#define DMARD10_RATE_32         32\r
-/*\r
-#define DMARD10_RATE_64         64\r
-#define DMARD10_RATE_120        128\r
-#define DMARD10_RATE_MIN               DMARD10_RATE_1\r
-#define DMARD10_RATE_MAX               DMARD10_RATE_120\r
-*/\r
-/*status*/\r
-#define DMARD10_OPEN               1\r
-#define DMARD10_CLOSE              0\r
-#define DMARD10_NORMAL            2\r
-#define DMARD10_LOWPOWER          3\r
-\r
-\r
-\r
-#define DMARD10_IIC_ADDR           0x18  \r
-#define DMARD10_REG_LEN         11\r
-\r
-\r
-#define DMARD10_FATOR  15 \r
-\r
-\r
-#define DMARD10_X_OUT          0x41\r
-#define SENSOR_DATA_SIZE 3\r
-#define DMARD10_SENSOR_RATE_1   0\r
-#define DMARD10_SENSOR_RATE_2   1\r
-#define DMARD10_SENSOR_RATE_3   2\r
-#define DMARD10_SENSOR_RATE_4   3\r
-\r
-#define POWER_OR_RATE 1\r
-#define SW_RESET 1\r
-#define DMARD10_INTERRUPUT 1\r
-#define DMARD10_POWERDOWN 0 \r
-#define DMARD10_POWERON 1 \r
-\r
-//g-senor layout configuration, choose one of the following configuration\r
-\r
-#define AVG_NUM                        16\r
-#define SENSOR_DATA_SIZE               3 \r
-#define DEFAULT_SENSITIVITY            1024\r
-\r
-\r
-\r
-#define DMARD10_ENABLE         1\r
-\r
-#define DMARD10_REG_X_OUT       0x12\r
-#define DMARD10_REG_Y_OUT       0x1\r
-#define DMARD10_REG_Z_OUT       0x2\r
-#define DMARD10_REG_TILT        0x3\r
-#define DMARD10_REG_SRST        0x4\r
-#define DMARD10_REG_SPCNT       0x5\r
-#define DMARD10_REG_INTSU       0x6\r
-#define DMARD10_REG_MODE        0x7\r
-#define DMARD10_REG_SR          0x8\r
-#define DMARD10_REG_PDET        0x9\r
-#define DMARD10_REG_PD          0xa\r
-\r
-#define DMARD10_RANGE                  4000000\r
-#define DMARD10_PRECISION       10\r
-#define DMARD10_BOUNDARY        (0x1 << (DMARD10_PRECISION  - 1)) \r
-#define DMARD10_GRAVITY_STEP    (DMARD10_RANGE / DMARD10_BOUNDARY)\r
-\r
-\r
-struct sensor_axis_average {\r
-               int x_average;\r
-               int y_average;\r
-               int z_average;\r
-               int count;\r
-};\r
-\r
-static struct sensor_axis_average axis_average;\r
-int gsensor_reset(struct i2c_client *client){\r
-       struct sensor_private_data *sensor =\r
-           (struct sensor_private_data *) i2c_get_clientdata(client);  \r
-       \r
-       char buffer[7], buffer2[2];\r
-       /* 1. check D10 , VALUE_STADR = 0x55 , VALUE_STAINT = 0xAA */\r
-       buffer[0] = REG_STADR;\r
-       buffer2[0] = REG_STAINT;\r
-       \r
-       sensor_rx_data(client, buffer, 2);\r
-       sensor_rx_data(client, buffer2, 2);\r
-               \r
-       if( buffer[0] == VALUE_STADR || buffer2[0] == VALUE_STAINT){\r
-               DBG(KERN_INFO " REG_STADR_VALUE = %d , REG_STAINT_VALUE = %d\n", buffer[0], buffer2[0]);\r
-               DBG(KERN_INFO " %s DMT_DEVICE_NAME registered I2C driver!\n",__FUNCTION__);\r
-       }\r
-       else{\r
-               DBG(KERN_INFO " %s gsensor I2C err @@@ REG_STADR_VALUE = %d , REG_STAINT_VALUE = %d \n", __func__, buffer[0], buffer2[0]);\r
-               return -1;\r
-       }\r
-       /* 2. Powerdown reset */\r
-       buffer[0] = REG_PD;\r
-       buffer[1] = VALUE_PD_RST;\r
-       sensor_tx_data(client, buffer, 2);\r
-       /* 3. ACTR => Standby mode => Download OTP to parameter reg => Standby mode => Reset data path => Standby mode */\r
-       buffer[0] = REG_ACTR;\r
-       buffer[1] = MODE_Standby;\r
-       buffer[2] = MODE_ReadOTP;\r
-       buffer[3] = MODE_Standby;\r
-       buffer[4] = MODE_ResetDataPath;\r
-       buffer[5] = MODE_Standby;\r
-       sensor_tx_data(client, buffer, 6);\r
-       /* 4. OSCA_EN = 1 ,TSTO = b'000(INT1 = normal, TEST0 = normal) */\r
-       buffer[0] = REG_MISC2;\r
-       buffer[1] = VALUE_MISC2_OSCA_EN;\r
-       sensor_tx_data(client, buffer, 2);\r
-       /* 5. AFEN = 1(AFE will powerdown after ADC) */\r
-       buffer[0] = REG_AFEM;\r
-       buffer[1] = VALUE_AFEM_AFEN_Normal;     \r
-       buffer[2] = VALUE_CKSEL_ODR_100_204;    \r
-       buffer[3] = VALUE_INTC; \r
-       buffer[4] = VALUE_TAPNS_Ave_2;\r
-       buffer[5] = 0x00;       // DLYC, no delay timing\r
-       buffer[6] = 0x07;       // INTD=1 (push-pull), INTA=1 (active high), AUTOT=1 (enable T)\r
-       sensor_tx_data(client, buffer, 7);\r
-       /* 6. write TCGYZ & TCGX */\r
-       buffer[0] = REG_WDAL;   // REG:0x01\r
-       buffer[1] = 0x00;               // set TC of Y,Z gain value\r
-       buffer[2] = 0x00;               // set TC of X gain value\r
-       buffer[3] = 0x03;               // Temperature coefficient of X,Y,Z gain\r
-       sensor_tx_data(client, buffer, 4);\r
-       \r
-       buffer[0] = REG_ACTR;                   // REG:0x00\r
-       buffer[1] = MODE_Standby;               // Standby\r
-       buffer[2] = MODE_WriteOTPBuf;   // WriteOTPBuf \r
-       buffer[3] = MODE_Standby;               // Standby\r
-       \r
-       /* 7. Activation mode */\r
-       buffer[0] = REG_ACTR;\r
-       buffer[1] = MODE_Active;\r
-       sensor_tx_data(client, buffer, 2);\r
-       printk("\n dmard10 gsensor _reset SUCCESS!!\n");\r
-       return 0;\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
-               gsensor_reset(client);\r
-       sensor->ops->ctrl_data = sensor_read_reg(client, sensor->ops->ctrl_reg);\r
-       //register setting according to chip datasheet          \r
-       if(enable)\r
-       {       \r
-               status = DMARD10_ENABLE;        //dmard10\r
-               sensor->ops->ctrl_data |= status;       \r
-       }\r
-       else\r
-       {\r
-               status = ~DMARD10_ENABLE;       //dmard10\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
-       DBG("%s:DMARD10_REG_TILT=0x%x\n",__func__,sensor_read_reg(client, DMARD10_REG_TILT));\r
-\r
-       result = sensor_write_reg(client, DMARD10_REG_SR, (0x01<<5)| 0x02);     //32 Samples/Second Active and Auto-Sleep Mode\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, DMARD10_REG_INTSU, 1<<4);//enable int,GINT=1\r
-               if(result)\r
-               {\r
-                       printk("%s:line=%d,error\n",__func__,__LINE__);\r
-                       return result;\r
-               }\r
-       }\r
-       \r
-       sensor->ops->ctrl_data = 1<<6;  //Interrupt output INT is push-pull\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
-       \r
-       memset(&axis_average, 0, sizeof(struct sensor_axis_average));\r
-\r
-       return result;\r
-}\r
-\r
-\r
-static int sensor_convert_data(struct i2c_client *client, char high_byte, char low_byte)\r
-{\r
-    s64 result;\r
-       \r
-        \r
-               result = ((int)high_byte << 8)|((int)low_byte);\r
-       \r
-               if (result < DMARD10_BOUNDARY){\r
-                       result = result* DMARD10_GRAVITY_STEP;\r
-               }else{\r
-                       result = ~( ((~result & (0x7fff>>(16-DMARD10_PRECISION)) ) + 1)* DMARD10_GRAVITY_STEP) + 1;\r
-               }\r
-                       \r
-               return result;\r
-\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
-#define DMARD10_COUNT_AVERAGE 2\r
-#define GSENSOR_MIN            2\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[8] = {0};   \r
-       char value = 0;\r
-       \r
-       if(sensor->ops->read_len < 3)   //sensor->ops->read_len = 3\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
-       /* 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[3], buffer[2]);  //buffer[1]:high bit \r
-       y = sensor_convert_data(sensor->client, buffer[5], buffer[4]);\r
-       z = sensor_convert_data(sensor->client, buffer[7], buffer[6]);          \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
-       \r
-       axis_average.x_average += axis.x;\r
-       axis_average.y_average += axis.y;\r
-       axis_average.z_average += axis.z;\r
-       axis_average.count++;\r
-       \r
-       if(axis_average.count >= DMARD10_COUNT_AVERAGE)\r
-       {\r
-               axis.x = axis_average.x_average / axis_average.count;   \r
-               axis.y = axis_average.y_average / axis_average.count;   \r
-               axis.z = axis_average.z_average / axis_average.count;\r
-               \r
-               DBG( "%s: axis = %d  %d  %d \n", __func__, axis.x, axis.y, axis.z);\r
-               \r
-               memset(&axis_average, 0, sizeof(struct sensor_axis_average));\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
-       \r
-       if((sensor->pdata->irq_enable)&& (sensor->ops->int_status_reg >= 0))    //read sensor intterupt status register\r
-       {\r
-               \r
-               value = sensor_read_reg(client, sensor->ops->int_status_reg);\r
-               DBG("%s:sensor int status :0x%x\n",__func__,value);\r
-       }\r
-       \r
-       return ret;\r
-}\r
-\r
-\r
-struct sensor_operate gsensor_dmard10_ops = {\r
-       .name                           = "gs_dmard10",\r
-       .type                           = SENSOR_TYPE_ACCEL,                    //sensor type and it should be correct\r
-       .id_i2c                         = ACCEL_ID_DMARD10,                     //i2c id number\r
-       .read_reg                       = DMARD10_REG_X_OUT,                    //read data\r
-       .read_len                       = 8,                                    //data length\r
-       .id_reg                         = SENSOR_UNKNOW_DATA,                   //read device id from this register\r
-       .id_data                        = SENSOR_UNKNOW_DATA,                   //device id\r
-       .precision                      = DMARD10_PRECISION,                    //12 bit\r
-       .ctrl_reg                       = DMARD10_REG_MODE,                     //enable or disable     \r
-       .int_status_reg         = SENSOR_UNKNOW_DATA,                   //intterupt status register\r
-       .range                          = {-DMARD10_RANGE,DMARD10_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
-static struct sensor_operate *gsensor_get_ops(void)\r
-{\r
-       return &gsensor_dmard10_ops;\r
-}\r
-\r
-\r
-static int __init gsensor_dmard10_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
-       return result;\r
-}\r
-\r
-static void __exit gsensor_dmard10_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_dmard10_init);\r
-module_exit(gsensor_dmard10_exit);\r
-\r
-\r
-\r
+/* drivers/input/sensors/access/dmard10.c
+ *
+ * Copyright (C) 2012-2015 ROCKCHIP.
+ * Author: guoyi <gy@rock-chips.com>
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+#include <linux/interrupt.h>
+#include <linux/i2c.h>
+#include <linux/slab.h>
+#include <linux/irq.h>
+#include <linux/miscdevice.h>
+#include <linux/gpio.h>
+#include <asm/uaccess.h>
+#include <asm/atomic.h>
+#include <linux/delay.h>
+#include <linux/input.h>
+#include <linux/workqueue.h>
+#include <linux/freezer.h>
+#include <linux/of_gpio.h>
+#ifdef CONFIG_HAS_EARLYSUSPEND
+#include <linux/earlysuspend.h>
+#endif
+#include <linux/sensor-dev.h>
+
+/* Default register settings */
+#define RBUFF_SIZE             12      /* Rx buffer size */
+
+#define REG_ACTR                               0x00
+#define REG_WDAL                               0x01
+#define REG_TAPNS                              0x0f
+#define REG_MISC2                              0x1f
+#define REG_AFEM                               0x0c
+#define REG_CKSEL                              0x0d
+#define REG_INTC                               0x0e
+#define REG_STADR                              0x12
+#define REG_STAINT                             0x1C
+#define REG_PD                                 0x21
+#define REG_TCGYZ                              0x26
+#define REG_X_OUT                              0x41
+
+#define MODE_Off                               0x00
+#define MODE_ResetAtOff                        0x01
+#define MODE_Standby                   0x02
+#define MODE_ResetAtStandby            0x03
+#define MODE_Active                            0x06
+#define MODE_Trigger                   0x0a
+#define MODE_ReadOTP                   0x12
+#define MODE_WriteOTP                  0x22
+#define MODE_WriteOTPBuf               0x42
+#define MODE_ResetDataPath             0x82
+
+#define VALUE_STADR                                    0x55
+#define VALUE_STAINT                           0xAA
+#define VALUE_AFEM_AFEN_Normal         0x8f// AFEN set 1 , ATM[2:0]=b'000(normal),EN_Z/Y/X/T=1
+#define VALUE_AFEM_Normal                      0x0f// AFEN set 0 , ATM[2:0]=b'000(normal),EN_Z/Y/X/T=1
+#define VALUE_INTC                                     0x00// INTC[6:5]=b'00
+#define VALUE_INTC_Interrupt_En                0x20// INTC[6:5]=b'01 (Data ready interrupt enable, active high at INT0)
+#define VALUE_CKSEL_ODR_0_204          0x04// ODR[3:0]=b'0000 (0.78125Hz), CCK[3:0]=b'0100 (204.8kHZ)
+#define VALUE_CKSEL_ODR_1_204          0x14// ODR[3:0]=b'0001 (1.5625Hz), CCK[3:0]=b'0100 (204.8kHZ)
+#define VALUE_CKSEL_ODR_3_204          0x24// ODR[3:0]=b'0010 (3.125Hz), CCK[3:0]=b'0100 (204.8kHZ)
+#define VALUE_CKSEL_ODR_6_204          0x34// ODR[3:0]=b'0011 (6.25Hz), CCK[3:0]=b'0100 (204.8kHZ)
+#define VALUE_CKSEL_ODR_12_204         0x44// ODR[3:0]=b'0100 (12.5Hz), CCK[3:0]=b'0100 (204.8kHZ)
+#define VALUE_CKSEL_ODR_25_204         0x54// ODR[3:0]=b'0101 (25Hz), CCK[3:0]=b'0100 (204.8kHZ)
+#define VALUE_CKSEL_ODR_50_204         0x64// ODR[3:0]=b'0110 (50Hz), CCK[3:0]=b'0100 (204.8kHZ)
+#define VALUE_CKSEL_ODR_100_204                0x74// ODR[3:0]=b'0111 (100Hz), CCK[3:0]=b'0100 (204.8kHZ)
+
+#define VALUE_TAPNS_NoFilter   0x00    // TAP1/TAP2    NO FILTER
+#define VALUE_TAPNS_Ave_2              0x11    // TAP1/TAP2    Average 2
+#define VALUE_TAPNS_Ave_4              0x22    // TAP1/TAP2    Average 4
+#define VALUE_TAPNS_Ave_8              0x33    // TAP1/TAP2    Average 8
+#define VALUE_TAPNS_Ave_16             0x44    // TAP1/TAP2    Average 16
+#define VALUE_TAPNS_Ave_32             0x55    // TAP1/TAP2    Average 32
+#define VALUE_MISC2_OSCA_EN            0x08
+#define VALUE_PD_RST                   0x52
+
+
+//#define DMARD10_REG_INTSU        0x47
+//#define DMARD10_REG_MODE        0x44
+//#define DMARD10_REG_SR               0x44
+
+
+#define DMARD10_REG_DS      0X49
+#define DMARD10_REG_ID       0X0F
+#define DMARD10_REG_IT       0X4D
+#define DMARD10_REG_INTSRC1_C       0X4A
+#define DMARD10_REG_INTSRC1_S       0X4B
+#define MMAIO                          0xA1
+
+// IOCTLs for DMARD10 library
+#define ECS_IOCTL_INIT                  _IO(MMAIO, 0x01)
+#define ECS_IOCTL_RESET                _IO(MMAIO, 0x04)
+#define ECS_IOCTL_CLOSE                        _IO(MMAIO, 0x02)
+#define ECS_IOCTL_START                        _IO(MMAIO, 0x03)
+#define ECS_IOCTL_GETDATA               _IOR(MMAIO, 0x08, char[RBUFF_SIZE+1])
+#define SENSOR_CALIBRATION             _IOWR(MMAIO, 0x05 , int[SENSOR_DATA_SIZE])
+
+// IOCTLs for APPs
+#define ECS_IOCTL_APP_SET_RATE         _IOW(MMAIO, 0x10, char)
+
+ //rate
+#define DMARD10_RANGE                                          2000000
+
+#define DMARD10_RATE_32         32
+/*
+#define DMARD10_RATE_64         64
+#define DMARD10_RATE_120        128
+#define DMARD10_RATE_MIN               DMARD10_RATE_1
+#define DMARD10_RATE_MAX               DMARD10_RATE_120
+*/
+/*status*/
+#define DMARD10_OPEN               1
+#define DMARD10_CLOSE              0
+#define DMARD10_NORMAL            2
+#define DMARD10_LOWPOWER          3
+
+
+
+#define DMARD10_IIC_ADDR           0x18
+#define DMARD10_REG_LEN         11
+
+
+#define DMARD10_FATOR  15
+
+
+#define DMARD10_X_OUT          0x41
+#define SENSOR_DATA_SIZE 3
+#define DMARD10_SENSOR_RATE_1   0
+#define DMARD10_SENSOR_RATE_2   1
+#define DMARD10_SENSOR_RATE_3   2
+#define DMARD10_SENSOR_RATE_4   3
+
+#define POWER_OR_RATE 1
+#define SW_RESET 1
+#define DMARD10_INTERRUPUT 1
+#define DMARD10_POWERDOWN 0
+#define DMARD10_POWERON 1
+
+//g-senor layout configuration, choose one of the following configuration
+
+#define AVG_NUM                        16
+#define SENSOR_DATA_SIZE               3
+#define DEFAULT_SENSITIVITY            1024
+
+
+
+#define DMARD10_ENABLE         1
+
+#define DMARD10_REG_X_OUT       0x12
+#define DMARD10_REG_Y_OUT       0x1
+#define DMARD10_REG_Z_OUT       0x2
+#define DMARD10_REG_TILT        0x3
+#define DMARD10_REG_SRST        0x4
+#define DMARD10_REG_SPCNT       0x5
+#define DMARD10_REG_INTSU       0x6
+#define DMARD10_REG_MODE        0x7
+#define DMARD10_REG_SR          0x8
+#define DMARD10_REG_PDET        0x9
+#define DMARD10_REG_PD          0xa
+
+#define DMARD10_RANGE                  4000000
+#define DMARD10_PRECISION       10
+#define DMARD10_BOUNDARY        (0x1 << (DMARD10_PRECISION  - 1))
+#define DMARD10_GRAVITY_STEP    (DMARD10_RANGE / DMARD10_BOUNDARY)
+
+
+struct sensor_axis_average {
+               int x_average;
+               int y_average;
+               int z_average;
+               int count;
+};
+
+static struct sensor_axis_average axis_average;
+int gsensor_reset(struct i2c_client *client){
+       struct sensor_private_data *sensor =
+           (struct sensor_private_data *) i2c_get_clientdata(client);
+
+       char buffer[7], buffer2[2];
+       /* 1. check D10 , VALUE_STADR = 0x55 , VALUE_STAINT = 0xAA */
+       buffer[0] = REG_STADR;
+       buffer2[0] = REG_STAINT;
+
+       sensor_rx_data(client, buffer, 2);
+       sensor_rx_data(client, buffer2, 2);
+
+       if( buffer[0] == VALUE_STADR || buffer2[0] == VALUE_STAINT){
+               DBG(KERN_INFO " REG_STADR_VALUE = %d , REG_STAINT_VALUE = %d\n", buffer[0], buffer2[0]);
+               DBG(KERN_INFO " %s DMT_DEVICE_NAME registered I2C driver!\n",__FUNCTION__);
+       }
+       else{
+               DBG(KERN_INFO " %s gsensor I2C err @@@ REG_STADR_VALUE = %d , REG_STAINT_VALUE = %d \n", __func__, buffer[0], buffer2[0]);
+               return -1;
+       }
+       /* 2. Powerdown reset */
+       buffer[0] = REG_PD;
+       buffer[1] = VALUE_PD_RST;
+       sensor_tx_data(client, buffer, 2);
+       /* 3. ACTR => Standby mode => Download OTP to parameter reg => Standby mode => Reset data path => Standby mode */
+       buffer[0] = REG_ACTR;
+       buffer[1] = MODE_Standby;
+       buffer[2] = MODE_ReadOTP;
+       buffer[3] = MODE_Standby;
+       buffer[4] = MODE_ResetDataPath;
+       buffer[5] = MODE_Standby;
+       sensor_tx_data(client, buffer, 6);
+       /* 4. OSCA_EN = 1 ,TSTO = b'000(INT1 = normal, TEST0 = normal) */
+       buffer[0] = REG_MISC2;
+       buffer[1] = VALUE_MISC2_OSCA_EN;
+       sensor_tx_data(client, buffer, 2);
+       /* 5. AFEN = 1(AFE will powerdown after ADC) */
+       buffer[0] = REG_AFEM;
+       buffer[1] = VALUE_AFEM_AFEN_Normal;
+       buffer[2] = VALUE_CKSEL_ODR_100_204;
+       buffer[3] = VALUE_INTC;
+       buffer[4] = VALUE_TAPNS_Ave_2;
+       buffer[5] = 0x00;       // DLYC, no delay timing
+       buffer[6] = 0x07;       // INTD=1 (push-pull), INTA=1 (active high), AUTOT=1 (enable T)
+       sensor_tx_data(client, buffer, 7);
+       /* 6. write TCGYZ & TCGX */
+       buffer[0] = REG_WDAL;   // REG:0x01
+       buffer[1] = 0x00;               // set TC of Y,Z gain value
+       buffer[2] = 0x00;               // set TC of X gain value
+       buffer[3] = 0x03;               // Temperature coefficient of X,Y,Z gain
+       sensor_tx_data(client, buffer, 4);
+
+       buffer[0] = REG_ACTR;                   // REG:0x00
+       buffer[1] = MODE_Standby;               // Standby
+       buffer[2] = MODE_WriteOTPBuf;   // WriteOTPBuf
+       buffer[3] = MODE_Standby;               // Standby
+
+       /* 7. Activation mode */
+       buffer[0] = REG_ACTR;
+       buffer[1] = MODE_Active;
+       sensor_tx_data(client, buffer, 2);
+       printk("\n dmard10 gsensor _reset SUCCESS!!\n");
+       return 0;
+}
+
+/****************operate according to sensor chip:start************/
+
+static int sensor_active(struct i2c_client *client, int enable, int rate)
+{
+       struct sensor_private_data *sensor =
+           (struct sensor_private_data *) i2c_get_clientdata(client);
+       int result = 0;
+       int status = 0;
+               gsensor_reset(client);
+       sensor->ops->ctrl_data = sensor_read_reg(client, sensor->ops->ctrl_reg);
+       //register setting according to chip datasheet
+       if(enable)
+       {
+               status = DMARD10_ENABLE;        //dmard10
+               sensor->ops->ctrl_data |= status;
+       }
+       else
+       {
+               status = ~DMARD10_ENABLE;       //dmard10
+               sensor->ops->ctrl_data &= status;
+       }
+
+       DBG("%s:reg=0x%x,reg_ctrl=0x%x,enable=%d\n",__func__,sensor->ops->ctrl_reg, sensor->ops->ctrl_data, enable);
+       result = sensor_write_reg(client, sensor->ops->ctrl_reg, sensor->ops->ctrl_data);
+       if(result)
+               printk("%s:fail to active sensor\n",__func__);
+
+       return result;
+
+}
+
+static int sensor_init(struct i2c_client *client)
+{
+       struct sensor_private_data *sensor =
+           (struct sensor_private_data *) i2c_get_clientdata(client);
+       int result = 0;
+
+       result = sensor->ops->active(client,0,0);
+       if(result)
+       {
+               printk("%s:line=%d,error\n",__func__,__LINE__);
+               return result;
+       }
+
+       sensor->status_cur = SENSOR_OFF;
+
+       DBG("%s:DMARD10_REG_TILT=0x%x\n",__func__,sensor_read_reg(client, DMARD10_REG_TILT));
+
+       result = sensor_write_reg(client, DMARD10_REG_SR, (0x01<<5)| 0x02);     //32 Samples/Second Active and Auto-Sleep Mode
+       if(result)
+       {
+               printk("%s:line=%d,error\n",__func__,__LINE__);
+               return result;
+       }
+
+       if(sensor->pdata->irq_enable)   //open interrupt
+       {
+               result = sensor_write_reg(client, DMARD10_REG_INTSU, 1<<4);//enable int,GINT=1
+               if(result)
+               {
+                       printk("%s:line=%d,error\n",__func__,__LINE__);
+                       return result;
+               }
+       }
+
+       sensor->ops->ctrl_data = 1<<6;  //Interrupt output INT is push-pull
+       result = sensor_write_reg(client, sensor->ops->ctrl_reg, sensor->ops->ctrl_data);
+       if(result)
+       {
+               printk("%s:line=%d,error\n",__func__,__LINE__);
+               return result;
+       }
+
+
+       memset(&axis_average, 0, sizeof(struct sensor_axis_average));
+
+       return result;
+}
+
+
+static int sensor_convert_data(struct i2c_client *client, char high_byte, char low_byte)
+{
+    s64 result;
+
+
+               result = ((int)high_byte << 8)|((int)low_byte);
+
+               if (result < DMARD10_BOUNDARY){
+                       result = result* DMARD10_GRAVITY_STEP;
+               }else{
+                       result = ~( ((~result & (0x7fff>>(16-DMARD10_PRECISION)) ) + 1)* DMARD10_GRAVITY_STEP) + 1;
+               }
+
+               return result;
+
+}
+
+static int gsensor_report_value(struct i2c_client *client, struct sensor_axis *axis)
+{
+       struct sensor_private_data *sensor =
+           (struct sensor_private_data *) i2c_get_clientdata(client);
+
+       /* Report acceleration sensor information */
+       input_report_abs(sensor->input_dev, ABS_X, axis->x);
+       input_report_abs(sensor->input_dev, ABS_Y, axis->y);
+       input_report_abs(sensor->input_dev, ABS_Z, axis->z);
+       input_sync(sensor->input_dev);
+       DBG("Gsensor x==%d  y==%d z==%d\n",axis->x,axis->y,axis->z);
+
+       return 0;
+}
+#define DMARD10_COUNT_AVERAGE 2
+#define GSENSOR_MIN            2
+static int sensor_report_value(struct i2c_client *client)
+{
+       struct sensor_private_data *sensor =
+               (struct sensor_private_data *) i2c_get_clientdata(client);
+       struct sensor_platform_data *pdata = sensor->pdata;
+       int ret = 0;
+       int x,y,z;
+       struct sensor_axis axis;
+       char buffer[8] = {0};
+       char value = 0;
+
+       if(sensor->ops->read_len < 3)   //sensor->ops->read_len = 3
+       {
+               printk("%s:lenth is error,len=%d\n",__func__,sensor->ops->read_len);
+               return -1;
+       }
+
+       memset(buffer, 0, 8);
+       /* Data bytes from hardware xL, xH, yL, yH, zL, zH */
+       do {
+               *buffer = sensor->ops->read_reg;
+               ret = sensor_rx_data(client, buffer, sensor->ops->read_len);
+               if (ret < 0)
+               return ret;
+       } while (0);
+
+       //this gsensor need 6 bytes buffer
+       x = sensor_convert_data(sensor->client, buffer[3], buffer[2]);  //buffer[1]:high bit
+       y = sensor_convert_data(sensor->client, buffer[5], buffer[4]);
+       z = sensor_convert_data(sensor->client, buffer[7], buffer[6]);
+
+       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;
+
+
+       axis_average.x_average += axis.x;
+       axis_average.y_average += axis.y;
+       axis_average.z_average += axis.z;
+       axis_average.count++;
+
+       if(axis_average.count >= DMARD10_COUNT_AVERAGE)
+       {
+               axis.x = axis_average.x_average / axis_average.count;
+               axis.y = axis_average.y_average / axis_average.count;
+               axis.z = axis_average.z_average / axis_average.count;
+
+               DBG( "%s: axis = %d  %d  %d \n", __func__, axis.x, axis.y, axis.z);
+
+               memset(&axis_average, 0, sizeof(struct sensor_axis_average));
+
+               //Report event only while value is changed to save some power
+               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))
+               {
+                       gsensor_report_value(client, &axis);
+
+                       /* »¥³âµØ»º´æÊý¾Ý. */
+                       mutex_lock(&(sensor->data_mutex) );
+                       sensor->axis = axis;
+                       mutex_unlock(&(sensor->data_mutex) );
+               }
+       }
+
+       if((sensor->pdata->irq_enable)&& (sensor->ops->int_status_reg >= 0))    //read sensor intterupt status register
+       {
+
+               value = sensor_read_reg(client, sensor->ops->int_status_reg);
+               DBG("%s:sensor int status :0x%x\n",__func__,value);
+       }
+
+       return ret;
+}
+
+
+struct sensor_operate gsensor_dmard10_ops = {
+       .name                           = "gs_dmard10",
+       .type                           = SENSOR_TYPE_ACCEL,                    //sensor type and it should be correct
+       .id_i2c                         = ACCEL_ID_DMARD10,                     //i2c id number
+       .read_reg                       = DMARD10_REG_X_OUT,                    //read data
+       .read_len                       = 8,                                    //data length
+       .id_reg                         = SENSOR_UNKNOW_DATA,                   //read device id from this register
+       .id_data                        = SENSOR_UNKNOW_DATA,                   //device id
+       .precision                      = DMARD10_PRECISION,                    //12 bit
+       .ctrl_reg                       = DMARD10_REG_MODE,                     //enable or disable
+       .int_status_reg         = SENSOR_UNKNOW_DATA,                   //intterupt status register
+       .range                          = {-DMARD10_RANGE,DMARD10_RANGE},       //range
+       .trig                           = IRQF_TRIGGER_LOW|IRQF_ONESHOT,
+       .active                         = sensor_active,
+       .init                           = sensor_init,
+       .report                         = sensor_report_value,
+};
+
+/****************operate according to sensor chip:end************/
+
+//function name should not be changed
+static struct sensor_operate *gsensor_get_ops(void)
+{
+       return &gsensor_dmard10_ops;
+}
+
+
+static int __init gsensor_dmard10_init(void)
+{
+       struct sensor_operate *ops = gsensor_get_ops();
+       int result = 0;
+       int type = ops->type;
+       result = sensor_register_slave(type, NULL, NULL, gsensor_get_ops);
+       return result;
+}
+
+static void __exit gsensor_dmard10_exit(void)
+{
+       struct sensor_operate *ops = gsensor_get_ops();
+       int type = ops->type;
+       sensor_unregister_slave(type, NULL, NULL, gsensor_get_ops);
+}
+
+
+module_init(gsensor_dmard10_init);
+module_exit(gsensor_dmard10_exit);
+
+
+