-# sensor drivers\r
-obj-$(CONFIG_ANGLE_DEVICE) += angle/\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
-obj-$(CONFIG_TEMPERATURE_DEVICE) += temperature/\r
-obj-$(CONFIG_PRESSURE_DEVICE) += pressure/\r
-obj-$(CONFIG_HALL_DEVICE) += hall/\r
-\r
-\r
-obj-$(CONFIG_SENSOR_DEVICE) += sensor-i2c.o\r
-obj-$(CONFIG_SENSOR_DEVICE) += sensor-dev.o\r
+# sensor drivers
+obj-$(CONFIG_ANGLE_DEVICE) += angle/
+obj-$(CONFIG_GSENSOR_DEVICE) += accel/
+obj-$(CONFIG_COMPASS_DEVICE) += compass/
+obj-$(CONFIG_GYROSCOPE_DEVICE) += gyro/
+obj-$(CONFIG_LIGHT_DEVICE) += lsensor/
+obj-$(CONFIG_PROXIMITY_DEVICE) += psensor/
+obj-$(CONFIG_TEMPERATURE_DEVICE) += temperature/
+obj-$(CONFIG_PRESSURE_DEVICE) += pressure/
+obj-$(CONFIG_HALL_DEVICE) += hall/
+
+
+obj-$(CONFIG_SENSOR_DEVICE) += sensor-i2c.o
+obj-$(CONFIG_SENSOR_DEVICE) += sensor-dev.o
-/* 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);
+
+
+
-/* drivers/input/sensors/access/kxtik.c\r
- *\r
- * Copyright (C) 2012-2015 ROCKCHIP.\r
- * Author: Bruins <xwj@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 <linux/of_gpio.h>\r
-#ifdef CONFIG_HAS_EARLYSUSPEND\r
-#include <linux/earlysuspend.h>\r
-#endif\r
-#include <linux/sensor-dev.h>\r
-\r
-\r
-#define LSM303D_WHO_AM_I (0x0F)\r
-\r
-/* full scale setting - register & mask */\r
-#define LSM303D_CTRL_REG0 (0x1F)\r
-#define LSM303D_CTRL_REG1 (0x20)\r
-#define LSM303D_CTRL_REG2 (0x21)\r
-#define LSM303D_CTRL_REG3 (0x22)\r
-#define LSM303D_CTRL_REG4 (0x23)\r
-#define LSM303D_CTRL_REG5 (0x24)\r
-#define LSM303D_CTRL_REG6 (0x25)\r
-#define LSM303D_CTRL_REG7 (0x26)\r
-#define LSM303D_STATUS_REG (0x27)\r
-#define LSM303D_OUT_X_L (0x28)\r
-#define LSM303D_OUT_X_H (0x29)\r
-#define LSM303D_OUT_Y_L (0x2a)\r
-#define LSM303D_OUT_Y_H (0x2b)\r
-#define LSM303D_OUT_Z_L (0x2c)\r
-#define LSM303D_OUT_Z_H (0x2d)\r
-#define LSM303D_FIFO_CTRL_REG (0x2E)\r
-#define LSM303D_FIFO_SRC_REG (0X2F)\r
-\r
-#define LSM303D_IG_CFG1 (0x30)\r
-#define LSM303D_IG_SRC1 (0x31)\r
-#define LSM303D_IG_THS1 (0x32)\r
-#define LSM303D_IG_DURATION1 (0x33)\r
-\r
-#define LSM303D_IG_CFG2 (0x34)\r
-#define LSM303D_IG_SRC2 (0x35)\r
-#define LSM303D_IG_THS2 (0x36)\r
-#define LSM303D_IG_DURATION2 (0x37)\r
-\r
-\r
-#define LSM303D_DEVID (0x49) //chip id\r
-#define LSM303D_ACC_DISABLE (0x08)\r
-\r
-#define LSM303D_RANGE 2000000\r
-\r
-/* LSM303D */\r
-#define LSM303D_PRECISION 16\r
-#define LSM303D_BOUNDARY (0x1 << (LSM303D_PRECISION - 1))\r
-#define LSM303D_GRAVITY_STEP (LSM303D_RANGE / LSM303D_BOUNDARY)\r
-\r
-#define ODR3P25 0x10 /* 3.25Hz output data rate */\r
-#define ODR6P25 0x20 /* 6.25Hz output data rate */\r
-#define ODR12P5 0x30 /* 12.5Hz output data rate */\r
-#define ODR25 0x40 /* 25Hz output data rate */\r
-#define ODR50 0x50 /* 50Hz output data rate */\r
-#define ODR100 0x60 /* 100Hz output data rate */\r
-#define ODR200 0x70 /* 200Hz output data rate */\r
-#define ODR400 0x80 /* 400Hz output data rate */\r
-#define ODR800 0x90 /* 800Hz output data rate */\r
-#define ODR1600 0xA0 /* 1600Hz output data rate */\r
-\r
-\r
-struct sensor_reg_data {\r
- char reg;\r
- char data;\r
-};\r
-\r
-/****************operate according to sensor chip:start************/\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
- sensor->ops->ctrl_data |= ODR100; //100HZ,if 0 then power down\r
- \r
- //register setting according to chip datasheet \r
- if(!enable)\r
- { \r
- status = LSM303D_ACC_DISABLE; //lis3dh \r
- sensor->ops->ctrl_data |= status; \r
- }\r
- else\r
- {\r
- status = ~LSM303D_ACC_DISABLE; //lis3dh\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
- int i;\r
-\r
- struct sensor_reg_data reg_data[] = \r
- {\r
- {LSM303D_CTRL_REG0,0x00},\r
- {LSM303D_CTRL_REG1,0x07},\r
- {LSM303D_CTRL_REG2,0x00},\r
- {LSM303D_CTRL_REG3,0x00},\r
- {LSM303D_CTRL_REG4,0x00},\r
- {LSM303D_CTRL_REG5,0x78}, //High resolution output mode:11,\r
- {LSM303D_CTRL_REG6,0x20},\r
- {LSM303D_CTRL_REG7,0x00},\r
- {LSM303D_FIFO_CTRL_REG,0x00},\r
- {LSM303D_IG_CFG1,0xFF}, //6 direction position recognition \r
- {LSM303D_IG_THS1,0x7F}, //Interrupt 1 threshold \r
- {LSM303D_IG_DURATION1,0x7F}, //Duration value 0x00->ox7f\r
- \r
- /*\r
- {LSM303D_CTRL_REG7,0x00}, \r
- {LSM303D_CTRL_REG4,0x08}, //High resolution output mode: 1, Normal mode \r
- {LSM303D_CTRL_REG6,0x40}, \r
- \r
- {LSM303D_FIFO_CTRL_REG,0x00}, // \r
- {LSM303D_IG_CFG1,0xFF}, //6 direction position recognition \r
- {LSM303D_IG_THS1,0x7F}, //Interrupt 1 threshold \r
- {LSM303D_IG_DURATION1,0x7F}, //Duration value 0x00->ox7f\r
- */\r
- }; \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
- for(i=0;i<(sizeof(reg_data)/sizeof(struct sensor_reg_data));i++)\r
- {\r
- result = sensor_write_reg(client, reg_data[i].reg, reg_data[i].data);\r
- if(result)\r
- {\r
- printk("%s:line=%d,i=%d,error\n",__func__,__LINE__,i);\r
- return result;\r
- }\r
- }\r
-\r
- \r
- if(sensor->pdata->irq_enable)\r
- {\r
-\r
- result = sensor_write_reg(client, LSM303D_CTRL_REG3, 0x20); \r
- if(result)\r
- {\r
- printk("%s:line=%d,error\n",__func__,__LINE__);\r
- return result;\r
- }\r
-\r
- i = sensor_read_reg(client,LSM303D_CTRL_REG5);\r
- \r
- result = sensor_write_reg(client, LSM303D_CTRL_REG5, (i|0x01));\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
-\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
- \r
- switch (sensor->devid) { \r
- case LSM303D_DEVID: \r
- result = ((int)high_byte << 8) | (int)low_byte;\r
- if (result < LSM303D_BOUNDARY)\r
- result = result* LSM303D_GRAVITY_STEP;\r
- else\r
- result = ~( ((~result & (0x7fff>>(16-LSM303D_PRECISION)) ) + 1) \r
- * LSM303D_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
- char value = 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
- value = sensor_read_reg(client, LSM303D_STATUS_REG);\r
- if((value & 0x0f) == 0)\r
- {\r
- printk("%s:line=%d,value=0x%x,data is not ready\n",__func__,__LINE__,value);\r
- return -1;\r
- }\r
- \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
- //printk( "%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
- 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
-struct sensor_operate gsensor_lsm303d_ops = {\r
- .name = "lsm303d",\r
- .type = SENSOR_TYPE_ACCEL, //sensor type and it should be correct\r
- .id_i2c = ACCEL_ID_LSM303D, //i2c id number\r
- .read_reg = (LSM303D_OUT_X_L | 0x80), //read data\r
- .read_len = 6, //data length\r
- .id_reg = LSM303D_WHO_AM_I, //read device id from this register\r
- .id_data = LSM303D_DEVID, //device id\r
- .precision = LSM303D_PRECISION, //16 bits\r
- .ctrl_reg = LSM303D_CTRL_REG1, //enable or disable \r
- .int_status_reg = LSM303D_IG_SRC1, //intterupt status register\r
- .range = {-LSM303D_RANGE,LSM303D_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
-\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_lsm303d_ops;\r
-}\r
-\r
-\r
-static int __init gsensor_lis3dh_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_lis3dh_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_lis3dh_init);\r
-module_exit(gsensor_lis3dh_exit);\r
-\r
-\r
-\r
-\r
+/* drivers/input/sensors/access/kxtik.c
+ *
+ * Copyright (C) 2012-2015 ROCKCHIP.
+ * Author: Bruins <xwj@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>
+
+
+#define LSM303D_WHO_AM_I (0x0F)
+
+/* full scale setting - register & mask */
+#define LSM303D_CTRL_REG0 (0x1F)
+#define LSM303D_CTRL_REG1 (0x20)
+#define LSM303D_CTRL_REG2 (0x21)
+#define LSM303D_CTRL_REG3 (0x22)
+#define LSM303D_CTRL_REG4 (0x23)
+#define LSM303D_CTRL_REG5 (0x24)
+#define LSM303D_CTRL_REG6 (0x25)
+#define LSM303D_CTRL_REG7 (0x26)
+#define LSM303D_STATUS_REG (0x27)
+#define LSM303D_OUT_X_L (0x28)
+#define LSM303D_OUT_X_H (0x29)
+#define LSM303D_OUT_Y_L (0x2a)
+#define LSM303D_OUT_Y_H (0x2b)
+#define LSM303D_OUT_Z_L (0x2c)
+#define LSM303D_OUT_Z_H (0x2d)
+#define LSM303D_FIFO_CTRL_REG (0x2E)
+#define LSM303D_FIFO_SRC_REG (0X2F)
+
+#define LSM303D_IG_CFG1 (0x30)
+#define LSM303D_IG_SRC1 (0x31)
+#define LSM303D_IG_THS1 (0x32)
+#define LSM303D_IG_DURATION1 (0x33)
+
+#define LSM303D_IG_CFG2 (0x34)
+#define LSM303D_IG_SRC2 (0x35)
+#define LSM303D_IG_THS2 (0x36)
+#define LSM303D_IG_DURATION2 (0x37)
+
+
+#define LSM303D_DEVID (0x49) //chip id
+#define LSM303D_ACC_DISABLE (0x08)
+
+#define LSM303D_RANGE 2000000
+
+/* LSM303D */
+#define LSM303D_PRECISION 16
+#define LSM303D_BOUNDARY (0x1 << (LSM303D_PRECISION - 1))
+#define LSM303D_GRAVITY_STEP (LSM303D_RANGE / LSM303D_BOUNDARY)
+
+#define ODR3P25 0x10 /* 3.25Hz output data rate */
+#define ODR6P25 0x20 /* 6.25Hz output data rate */
+#define ODR12P5 0x30 /* 12.5Hz output data rate */
+#define ODR25 0x40 /* 25Hz output data rate */
+#define ODR50 0x50 /* 50Hz output data rate */
+#define ODR100 0x60 /* 100Hz output data rate */
+#define ODR200 0x70 /* 200Hz output data rate */
+#define ODR400 0x80 /* 400Hz output data rate */
+#define ODR800 0x90 /* 800Hz output data rate */
+#define ODR1600 0xA0 /* 1600Hz output data rate */
+
+
+struct sensor_reg_data {
+ char reg;
+ char data;
+};
+
+/****************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;
+
+ sensor->ops->ctrl_data = sensor_read_reg(client, sensor->ops->ctrl_reg);
+
+ sensor->ops->ctrl_data |= ODR100; //100HZ,if 0 then power down
+
+ //register setting according to chip datasheet
+ if(!enable)
+ {
+ status = LSM303D_ACC_DISABLE; //lis3dh
+ sensor->ops->ctrl_data |= status;
+ }
+ else
+ {
+ status = ~LSM303D_ACC_DISABLE; //lis3dh
+ 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;
+ int i;
+
+ struct sensor_reg_data reg_data[] =
+ {
+ {LSM303D_CTRL_REG0,0x00},
+ {LSM303D_CTRL_REG1,0x07},
+ {LSM303D_CTRL_REG2,0x00},
+ {LSM303D_CTRL_REG3,0x00},
+ {LSM303D_CTRL_REG4,0x00},
+ {LSM303D_CTRL_REG5,0x78}, //High resolution output mode:11,
+ {LSM303D_CTRL_REG6,0x20},
+ {LSM303D_CTRL_REG7,0x00},
+ {LSM303D_FIFO_CTRL_REG,0x00},
+ {LSM303D_IG_CFG1,0xFF}, //6 direction position recognition
+ {LSM303D_IG_THS1,0x7F}, //Interrupt 1 threshold
+ {LSM303D_IG_DURATION1,0x7F}, //Duration value 0x00->ox7f
+
+ /*
+ {LSM303D_CTRL_REG7,0x00},
+ {LSM303D_CTRL_REG4,0x08}, //High resolution output mode: 1, Normal mode
+ {LSM303D_CTRL_REG6,0x40},
+
+ {LSM303D_FIFO_CTRL_REG,0x00}, //
+ {LSM303D_IG_CFG1,0xFF}, //6 direction position recognition
+ {LSM303D_IG_THS1,0x7F}, //Interrupt 1 threshold
+ {LSM303D_IG_DURATION1,0x7F}, //Duration value 0x00->ox7f
+ */
+ };
+
+ result = sensor->ops->active(client,0,0);
+ if(result)
+ {
+ printk("%s:line=%d,error\n",__func__,__LINE__);
+ return result;
+ }
+
+ sensor->status_cur = SENSOR_OFF;
+
+ for(i=0;i<(sizeof(reg_data)/sizeof(struct sensor_reg_data));i++)
+ {
+ result = sensor_write_reg(client, reg_data[i].reg, reg_data[i].data);
+ if(result)
+ {
+ printk("%s:line=%d,i=%d,error\n",__func__,__LINE__,i);
+ return result;
+ }
+ }
+
+
+ if(sensor->pdata->irq_enable)
+ {
+
+ result = sensor_write_reg(client, LSM303D_CTRL_REG3, 0x20);
+ if(result)
+ {
+ printk("%s:line=%d,error\n",__func__,__LINE__);
+ return result;
+ }
+
+ i = sensor_read_reg(client,LSM303D_CTRL_REG5);
+
+ result = sensor_write_reg(client, LSM303D_CTRL_REG5, (i|0x01));
+ if(result)
+ {
+ printk("%s:line=%d,error\n",__func__,__LINE__);
+ return result;
+ }
+
+ }
+
+ return result;
+}
+
+
+static int sensor_convert_data(struct i2c_client *client, char high_byte, char low_byte)
+{
+ s64 result;
+ struct sensor_private_data *sensor =
+ (struct sensor_private_data *) i2c_get_clientdata(client);
+
+ switch (sensor->devid) {
+ case LSM303D_DEVID:
+ result = ((int)high_byte << 8) | (int)low_byte;
+ if (result < LSM303D_BOUNDARY)
+ result = result* LSM303D_GRAVITY_STEP;
+ else
+ result = ~( ((~result & (0x7fff>>(16-LSM303D_PRECISION)) ) + 1)
+ * LSM303D_GRAVITY_STEP) + 1;
+ break;
+
+ default:
+ printk(KERN_ERR "%s: devid wasn't set correctly\n",__func__);
+ return -EFAULT;
+ }
+
+ return (int)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 GSENSOR_MIN 10
+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[6] = {0};
+ char value = 0;
+
+ if(sensor->ops->read_len < 6) //sensor->ops->read_len = 6
+ {
+ printk("%s:lenth is error,len=%d\n",__func__,sensor->ops->read_len);
+ return -1;
+ }
+
+ memset(buffer, 0, 6);
+
+ value = sensor_read_reg(client, LSM303D_STATUS_REG);
+ if((value & 0x0f) == 0)
+ {
+ printk("%s:line=%d,value=0x%x,data is not ready\n",__func__,__LINE__,value);
+ return -1;
+ }
+
+
+ /* 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[1], buffer[0]); //buffer[1]:high bit
+ y = sensor_convert_data(sensor->client, buffer[3], buffer[2]);
+ z = sensor_convert_data(sensor->client, buffer[5], buffer[4]);
+
+ 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;
+
+ DBG( "%s: axis = %d %d %d \n", __func__, axis.x, axis.y, axis.z);
+ //printk( "%s: axis = %d %d %d \n", __func__, axis.x, axis.y, axis.z);
+
+ //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_lsm303d_ops = {
+ .name = "lsm303d",
+ .type = SENSOR_TYPE_ACCEL, //sensor type and it should be correct
+ .id_i2c = ACCEL_ID_LSM303D, //i2c id number
+ .read_reg = (LSM303D_OUT_X_L | 0x80), //read data
+ .read_len = 6, //data length
+ .id_reg = LSM303D_WHO_AM_I, //read device id from this register
+ .id_data = LSM303D_DEVID, //device id
+ .precision = LSM303D_PRECISION, //16 bits
+ .ctrl_reg = LSM303D_CTRL_REG1, //enable or disable
+ .int_status_reg = LSM303D_IG_SRC1, //intterupt status register
+ .range = {-LSM303D_RANGE,LSM303D_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_lsm303d_ops;
+}
+
+
+static int __init gsensor_lis3dh_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_lis3dh_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_lis3dh_init);
+module_exit(gsensor_lis3dh_exit);
+
+
+
+
-obj-$(CONFIG_ANGLE_KXTIK) += angle_kxtik.o\r
-obj-$(CONFIG_ANGLE_LIS3DH) += angle_lis3dh.o\r
+obj-$(CONFIG_ANGLE_KXTIK) += angle_kxtik.o
+obj-$(CONFIG_ANGLE_LIS3DH) += angle_lis3dh.o
-/* drivers/input/sensors/access/akm09911.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 <linux/of_gpio.h>\r
-#ifdef CONFIG_HAS_EARLYSUSPEND\r
-#include <linux/earlysuspend.h>\r
-#endif\r
-#include <linux/sensor-dev.h>\r
-\r
-\r
-\r
-#define SENSOR_DATA_SIZE 9\r
-#define YPR_DATA_SIZE 16\r
-#define RWBUF_SIZE 16\r
-\r
-#define ACC_DATA_FLAG 0\r
-#define MAG_DATA_FLAG 1\r
-#define ORI_DATA_FLAG 2\r
-#define AKM_NUM_SENSORS 3\r
-\r
-#define ACC_DATA_READY (1<<(ACC_DATA_FLAG))\r
-#define MAG_DATA_READY (1<<(MAG_DATA_FLAG))\r
-#define ORI_DATA_READY (1<<(ORI_DATA_FLAG))\r
-\r
-/*Constant definitions of the AK09911.*/\r
-#define AK09911_MEASUREMENT_TIME_US 10000\r
-\r
-#define AK09911_MODE_SNG_MEASURE 0x01\r
-#define AK09911_MODE_SELF_TEST 0x10\r
-#define AK09911_MODE_FUSE_ACCESS 0x1F\r
-#define AK09911_MODE_POWERDOWN 0x00\r
-#define AK09911_RESET_DATA 0x01\r
-\r
-\r
-/* Device specific constant values */\r
-#define AK09911_REG_WIA1 0x00\r
-#define AK09911_REG_WIA2 0x01\r
-#define AK09911_REG_INFO1 0x02\r
-#define AK09911_REG_INFO2 0x03\r
-#define AK09911_REG_ST1 0x10\r
-#define AK09911_REG_HXL 0x11\r
-#define AK09911_REG_HXH 0x12\r
-#define AK09911_REG_HYL 0x13\r
-#define AK09911_REG_HYH 0x14\r
-#define AK09911_REG_HZL 0x15\r
-#define AK09911_REG_HZH 0x16\r
-#define AK09911_REG_TMPS 0x17\r
-#define AK09911_REG_ST2 0x18\r
-#define AK09911_REG_CNTL1 0x30\r
-#define AK09911_REG_CNTL2 0x31\r
-#define AK09911_REG_CNTL3 0x32\r
-\r
-\r
-#define AK09911_FUSE_ASAX 0x60\r
-#define AK09911_FUSE_ASAY 0x61\r
-#define AK09911_FUSE_ASAZ 0x62\r
-\r
-#define AK09911_INFO_SIZE 2\r
-#define AK09911_CONF_SIZE 3\r
-\r
-\r
-\r
-#define COMPASS_IOCTL_MAGIC 'c'\r
-\r
-/* IOCTLs for AKM library */\r
-#define ECS_IOCTL_WRITE _IOW(COMPASS_IOCTL_MAGIC, 0x01, char*)\r
-#define ECS_IOCTL_READ _IOWR(COMPASS_IOCTL_MAGIC, 0x02, char*)\r
-#define ECS_IOCTL_RESET _IO(COMPASS_IOCTL_MAGIC, 0x03) /* NOT used in AK8975 */\r
-#define ECS_IOCTL_SET_MODE _IOW(COMPASS_IOCTL_MAGIC, 0x04, short)\r
-#define ECS_IOCTL_GETDATA _IOR(COMPASS_IOCTL_MAGIC, 0x05, char[8])\r
-#define ECS_IOCTL_SET_YPR _IOW(COMPASS_IOCTL_MAGIC, 0x06, short[12])\r
-#define ECS_IOCTL_GET_OPEN_STATUS _IOR(COMPASS_IOCTL_MAGIC, 0x07, int)\r
-#define ECS_IOCTL_GET_CLOSE_STATUS _IOR(COMPASS_IOCTL_MAGIC, 0x08, int)\r
-#define ECS_IOCTL_GET_LAYOUT _IOR(COMPASS_IOCTL_MAGIC, 0x09, char)\r
-#define ECS_IOCTL_GET_ACCEL _IOR(COMPASS_IOCTL_MAGIC, 0x0A, short[3])\r
-#define ECS_IOCTL_GET_OUTBIT _IOR(COMPASS_IOCTL_MAGIC, 0x0B, char)\r
-#define ECS_IOCTL_GET_INFO _IOR(COMPASS_IOCTL_MAGIC, 0x0C, short)\r
-#define ECS_IOCTL_GET_CONF _IOR(COMPASS_IOCTL_MAGIC, 0x0D, short)\r
-#define ECS_IOCTL_GET_PLATFORM_DATA _IOR(COMPASS_IOCTL_MAGIC, 0x0E, struct akm_platform_data)\r
-#define ECS_IOCTL_GET_DELAY _IOR(COMPASS_IOCTL_MAGIC, 0x30, short)\r
-\r
-\r
-\r
-#define AK09911_DEVICE_ID 0x05\r
-static struct i2c_client *this_client;\r
-static struct miscdevice compass_dev_device;\r
-\r
-static short g_akm_rbuf[12];\r
-static char g_sensor_info[AK09911_INFO_SIZE];\r
-static char g_sensor_conf[AK09911_CONF_SIZE];\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
- \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
- sensor->ops->ctrl_data = AK09911_MODE_SNG_MEASURE; \r
- }\r
- else\r
- {\r
- sensor->ops->ctrl_data = AK09911_MODE_POWERDOWN;\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
- result = misc_register(&compass_dev_device);\r
- if (result < 0) {\r
- printk("%s:fail to register misc device %s\n", __func__, compass_dev_device.name);\r
- result = -1;\r
- }\r
-\r
- g_sensor_info[0] = AK09911_REG_WIA1;\r
- result = sensor_rx_data(client, g_sensor_info, AK09911_INFO_SIZE);\r
- if(result)\r
- {\r
- printk("%s:line=%d,error\n",__func__,__LINE__);\r
- return result;\r
- }\r
-\r
- \r
- g_sensor_conf[0] = AK09911_FUSE_ASAX;\r
- result = sensor_rx_data(client, g_sensor_conf, AK09911_CONF_SIZE);\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[SENSOR_DATA_SIZE] = {0}; \r
- unsigned char *stat;\r
- unsigned char *stat2; \r
- int ret = 0; \r
- char value = 0;\r
- int i;\r
-\r
- if(sensor->ops->read_len < SENSOR_DATA_SIZE) //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, SENSOR_DATA_SIZE);\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
+/* drivers/input/sensors/access/akm09911.c
+ *
+ * Copyright (C) 2012-2015 ROCKCHIP.
+ * Author: luowei <lw@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>
+
+
+
+#define SENSOR_DATA_SIZE 9
+#define YPR_DATA_SIZE 16
+#define RWBUF_SIZE 16
+
+#define ACC_DATA_FLAG 0
+#define MAG_DATA_FLAG 1
+#define ORI_DATA_FLAG 2
+#define AKM_NUM_SENSORS 3
+
+#define ACC_DATA_READY (1<<(ACC_DATA_FLAG))
+#define MAG_DATA_READY (1<<(MAG_DATA_FLAG))
+#define ORI_DATA_READY (1<<(ORI_DATA_FLAG))
+
+/*Constant definitions of the AK09911.*/
+#define AK09911_MEASUREMENT_TIME_US 10000
+
+#define AK09911_MODE_SNG_MEASURE 0x01
+#define AK09911_MODE_SELF_TEST 0x10
+#define AK09911_MODE_FUSE_ACCESS 0x1F
+#define AK09911_MODE_POWERDOWN 0x00
+#define AK09911_RESET_DATA 0x01
+
+
+/* Device specific constant values */
+#define AK09911_REG_WIA1 0x00
+#define AK09911_REG_WIA2 0x01
+#define AK09911_REG_INFO1 0x02
+#define AK09911_REG_INFO2 0x03
+#define AK09911_REG_ST1 0x10
+#define AK09911_REG_HXL 0x11
+#define AK09911_REG_HXH 0x12
+#define AK09911_REG_HYL 0x13
+#define AK09911_REG_HYH 0x14
+#define AK09911_REG_HZL 0x15
+#define AK09911_REG_HZH 0x16
+#define AK09911_REG_TMPS 0x17
+#define AK09911_REG_ST2 0x18
+#define AK09911_REG_CNTL1 0x30
+#define AK09911_REG_CNTL2 0x31
+#define AK09911_REG_CNTL3 0x32
+
+
+#define AK09911_FUSE_ASAX 0x60
+#define AK09911_FUSE_ASAY 0x61
+#define AK09911_FUSE_ASAZ 0x62
+
+#define AK09911_INFO_SIZE 2
+#define AK09911_CONF_SIZE 3
+
+
+
+#define COMPASS_IOCTL_MAGIC 'c'
+
+/* IOCTLs for AKM library */
+#define ECS_IOCTL_WRITE _IOW(COMPASS_IOCTL_MAGIC, 0x01, char*)
+#define ECS_IOCTL_READ _IOWR(COMPASS_IOCTL_MAGIC, 0x02, char*)
+#define ECS_IOCTL_RESET _IO(COMPASS_IOCTL_MAGIC, 0x03) /* NOT used in AK8975 */
+#define ECS_IOCTL_SET_MODE _IOW(COMPASS_IOCTL_MAGIC, 0x04, short)
+#define ECS_IOCTL_GETDATA _IOR(COMPASS_IOCTL_MAGIC, 0x05, char[8])
+#define ECS_IOCTL_SET_YPR _IOW(COMPASS_IOCTL_MAGIC, 0x06, short[12])
+#define ECS_IOCTL_GET_OPEN_STATUS _IOR(COMPASS_IOCTL_MAGIC, 0x07, int)
+#define ECS_IOCTL_GET_CLOSE_STATUS _IOR(COMPASS_IOCTL_MAGIC, 0x08, int)
+#define ECS_IOCTL_GET_LAYOUT _IOR(COMPASS_IOCTL_MAGIC, 0x09, char)
+#define ECS_IOCTL_GET_ACCEL _IOR(COMPASS_IOCTL_MAGIC, 0x0A, short[3])
+#define ECS_IOCTL_GET_OUTBIT _IOR(COMPASS_IOCTL_MAGIC, 0x0B, char)
+#define ECS_IOCTL_GET_INFO _IOR(COMPASS_IOCTL_MAGIC, 0x0C, short)
+#define ECS_IOCTL_GET_CONF _IOR(COMPASS_IOCTL_MAGIC, 0x0D, short)
+#define ECS_IOCTL_GET_PLATFORM_DATA _IOR(COMPASS_IOCTL_MAGIC, 0x0E, struct akm_platform_data)
+#define ECS_IOCTL_GET_DELAY _IOR(COMPASS_IOCTL_MAGIC, 0x30, short)
+
+
+
+#define AK09911_DEVICE_ID 0x05
+static struct i2c_client *this_client;
+static struct miscdevice compass_dev_device;
+
+static short g_akm_rbuf[12];
+static char g_sensor_info[AK09911_INFO_SIZE];
+static char g_sensor_conf[AK09911_CONF_SIZE];
+
+
+/****************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;
+
+ //sensor->ops->ctrl_data = sensor_read_reg(client, sensor->ops->ctrl_reg);
+
+ //register setting according to chip datasheet
+ if(enable)
+ {
+ sensor->ops->ctrl_data = AK09911_MODE_SNG_MEASURE;
+ }
+ else
+ {
+ sensor->ops->ctrl_data = AK09911_MODE_POWERDOWN;
+ }
+
+ 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;
+
+ this_client = client;
+
+ result = sensor->ops->active(client,0,0);
+ if(result)
+ {
+ printk("%s:line=%d,error\n",__func__,__LINE__);
+ return result;
+ }
+
+ sensor->status_cur = SENSOR_OFF;
+
+ result = misc_register(&compass_dev_device);
+ if (result < 0) {
+ printk("%s:fail to register misc device %s\n", __func__, compass_dev_device.name);
+ result = -1;
+ }
+
+ g_sensor_info[0] = AK09911_REG_WIA1;
+ result = sensor_rx_data(client, g_sensor_info, AK09911_INFO_SIZE);
+ if(result)
+ {
+ printk("%s:line=%d,error\n",__func__,__LINE__);
+ return result;
+ }
+
+
+ g_sensor_conf[0] = AK09911_FUSE_ASAX;
+ result = sensor_rx_data(client, g_sensor_conf, AK09911_CONF_SIZE);
+ if(result)
+ {
+ printk("%s:line=%d,error\n",__func__,__LINE__);
+ return result;
+ }
+
+ DBG("%s:status_cur=%d\n",__func__, sensor->status_cur);
+ return result;
+}
+
+static int sensor_report_value(struct i2c_client *client)
+{
+ struct sensor_private_data *sensor =
+ (struct sensor_private_data *) i2c_get_clientdata(client);
+ char buffer[SENSOR_DATA_SIZE] = {0};
+ unsigned char *stat;
+ unsigned char *stat2;
+ int ret = 0;
+ char value = 0;
+ int i;
+
+ if(sensor->ops->read_len < SENSOR_DATA_SIZE) //sensor->ops->read_len = 8
+ {
+ printk("%s:lenth is error,len=%d\n",__func__,sensor->ops->read_len);
+ return -1;
+ }
+
+ memset(buffer, 0, SENSOR_DATA_SIZE);
+
+ /* 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);
+
+ stat = &buffer[0];
+ stat2 = &buffer[7];
+
+ /*
* 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
-#if 0\r
+ */
+ if ((*stat & 0x01) != 0x01) {
+ DBG(KERN_ERR "%s:ST is not set\n",__func__);
+ return -1;
+ }
+#if 0
/*
* ST2 : data error -
* occurs when data read is started outside of a readable period;
* 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
+ if (*stat2 & 0x04)
+ {
+ DBG(KERN_ERR "%s:compass data error\n",__func__);
+ return -2;
+ }
+
/*
* ST2 : overflow -
* the sum of the absolute values of all axis |X|+|Y|+|Z| < 2400uT.
* 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
-#endif\r
- /* »¥³âµØ»º´æÊý¾Ý. */\r
- mutex_lock(&sensor->data_mutex); \r
- memcpy(sensor->sensor_data, buffer, sensor->ops->read_len);\r
- mutex_unlock(&sensor->data_mutex);\r
- DBG("%s:",__func__);\r
- for(i=0; i<sensor->ops->read_len; i++)\r
- DBG("0x%x,",buffer[i]);\r
- DBG("\n");\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
- \r
- //trigger next measurement \r
- ret = sensor_write_reg(client, sensor->ops->ctrl_reg, sensor->ops->ctrl_data);\r
- if(ret)\r
- {\r
- printk(KERN_ERR "%s:fail to set ctrl_data:0x%x\n",__func__,sensor->ops->ctrl_data);\r
- return ret;\r
- }\r
-\r
- return ret;\r
-}\r
-\r
-static void compass_set_YPR(int *rbuf)\r
-{\r
- struct sensor_private_data *sensor =\r
- (struct sensor_private_data *) i2c_get_clientdata(this_client); \r
-\r
- /* No events are reported */\r
- if (!rbuf[0]) {\r
- printk("%s:Don't waste a time.",__func__);\r
- return;\r
- }\r
-\r
- DBG("%s:buf[0]=0x%x\n",__func__, rbuf[0]);\r
- \r
- /* Report magnetic sensor information */\r
- if (atomic_read(&sensor->flags.m_flag) && (rbuf[0] & ORI_DATA_READY)) {\r
- input_report_abs(sensor->input_dev, ABS_RX, rbuf[9]);\r
- input_report_abs(sensor->input_dev, ABS_RY, rbuf[10]);\r
- input_report_abs(sensor->input_dev, ABS_RZ, rbuf[11]);\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[9], rbuf[10], rbuf[11], rbuf[4]);\r
- }\r
- \r
- /* Report acceleration sensor information */\r
- if (atomic_read(&sensor->flags.a_flag) && (rbuf[0] & ACC_DATA_READY)) {\r
- input_report_abs(sensor->input_dev, ABS_X, rbuf[1]);\r
- input_report_abs(sensor->input_dev, ABS_Y, rbuf[2]);\r
- input_report_abs(sensor->input_dev, ABS_Z, rbuf[3]);\r
- input_report_abs(sensor->input_dev, ABS_WHEEL, rbuf[4]);\r
- \r
- DBG("%s:a_flag:x=%d,y=%d,z=%d,WHEEL=%d\n",__func__,rbuf[1], rbuf[2], rbuf[3], rbuf[4]);\r
- }\r
- \r
- /* Report magnetic vector information */\r
- if (atomic_read(&sensor->flags.mv_flag) && (rbuf[0] & MAG_DATA_READY)) {\r
- input_report_abs(sensor->input_dev, ABS_HAT0X, rbuf[5]);\r
- input_report_abs(sensor->input_dev, ABS_HAT0Y, rbuf[6]);\r
- input_report_abs(sensor->input_dev, ABS_BRAKE, rbuf[7]); \r
- input_report_abs(sensor->input_dev, ABS_HAT1X, rbuf[8]);\r
- \r
- DBG("%s:mv_flag:x=%d,y=%d,z=%d,status=%d\n",__func__,rbuf[5], rbuf[6], rbuf[7], rbuf[8]);\r
- }\r
- \r
- input_sync(sensor->input_dev);\r
-\r
- memcpy(g_akm_rbuf, rbuf, 12); //used for ECS_IOCTL_GET_ACCEL\r
-}\r
-\r
-\r
-\r
-static int compass_dev_open(struct inode *inode, struct file *file)\r
-{\r
- struct sensor_private_data* sensor = \r
- (struct sensor_private_data *)i2c_get_clientdata(this_client); \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
- struct sensor_private_data* sensor = \r
- (struct sensor_private_data *)i2c_get_clientdata(this_client); \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 & 0x1f)\r
- {\r
- case AK09911_MODE_SNG_MEASURE:\r
- case AK09911_MODE_SELF_TEST: \r
- case AK09911_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 AK09911_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 & 0x1f)\r
- {\r
- case AK09911_MODE_SNG_MEASURE: \r
- result = sensor_write_reg(client, sensor->ops->ctrl_reg, AK09911_MODE_SNG_MEASURE);\r
- if(result)\r
- printk("%s:i2c error,mode=%d\n",__func__,mode); \r
- break;\r
- case AK09911_MODE_SELF_TEST: \r
- result = sensor_write_reg(client, sensor->ops->ctrl_reg, AK09911_MODE_SELF_TEST);\r
- if(result)\r
- printk("%s:i2c error,mode=%d\n",__func__,mode);\r
- break;\r
- case AK09911_MODE_FUSE_ACCESS:\r
- result = sensor_write_reg(client, sensor->ops->ctrl_reg, AK09911_MODE_FUSE_ACCESS);\r
- if(result)\r
- printk("%s:i2c error,mode=%d\n",__func__,mode);\r
- break;\r
- case AK09911_MODE_POWERDOWN:\r
- /* Set powerdown mode */\r
- result = sensor_write_reg(client, sensor->ops->ctrl_reg, AK09911_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=0x%x\n",__func__,mode);\r
- return result;\r
-\r
-}\r
-\r
-static int compass_akm_reset(struct i2c_client *client)\r
-{\r
- struct sensor_private_data* sensor = (struct sensor_private_data *)i2c_get_clientdata(this_client); \r
- int result = 0; \r
- \r
- if(sensor->pdata->reset_pin > 0)\r
- {\r
- gpio_direction_output(sensor->pdata->reset_pin, GPIO_LOW);\r
- udelay(10);\r
- gpio_direction_output(sensor->pdata->reset_pin, GPIO_HIGH);\r
- }\r
- else \r
- {\r
- /* Set measure mode */\r
- result = sensor_write_reg(client, sensor->ops->ctrl_reg, AK09911_MODE_SNG_MEASURE);\r
- if(result)\r
- printk("%s:fail to Set measure mode\n",__func__);\r
- }\r
- \r
- udelay(100);\r
- \r
- return result;\r
-\r
-}\r
-\r
-\r
-\r
-static int compass_akm_get_openstatus(void)\r
-{ \r
- struct sensor_private_data* sensor = (struct sensor_private_data *)i2c_get_clientdata(this_client); \r
- wait_event_interruptible(sensor->flags.open_wq, (atomic_read(&sensor->flags.open_flag) != 0));\r
- return atomic_read(&sensor->flags.open_flag);\r
-}\r
-\r
-static int compass_akm_get_closestatus(void)\r
-{ \r
- struct sensor_private_data* sensor = (struct sensor_private_data *)i2c_get_clientdata(this_client); \r
- wait_event_interruptible(sensor->flags.open_wq, (atomic_read(&sensor->flags.open_flag) <= 0));\r
- return atomic_read(&sensor->flags.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 akm_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
- int value[YPR_DATA_SIZE]; /* for SET_YPR */\r
- int status; /* for OPEN/CLOSE_STATUS */\r
- int ret = -1; /* Return value. */\r
- \r
- //int8_t sensor_buf[SENSOR_DATA_SIZE]; /* for GETDATA */\r
- //int32_t ypr_buf[YPR_DATA_SIZE]; /* for SET_YPR */\r
- int16_t acc_buf[3]; /* for GET_ACCEL */\r
- int64_t delay[AKM_NUM_SENSORS]; /* for GET_DELAY */\r
- char layout; /* for GET_LAYOUT */\r
- char outbit; /* for GET_OUTBIT */\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
- case ECS_IOCTL_GETDATA:\r
- case ECS_IOCTL_GET_OPEN_STATUS:\r
- case ECS_IOCTL_GET_CLOSE_STATUS:\r
- case ECS_IOCTL_GET_DELAY:\r
- case ECS_IOCTL_GET_LAYOUT:\r
- case ECS_IOCTL_GET_OUTBIT:\r
- case ECS_IOCTL_GET_ACCEL:\r
- case ECS_IOCTL_GET_INFO:\r
- case ECS_IOCTL_GET_CONF:\r
- /* Just check buffer pointer */\r
- if (argp == NULL) {\r
- printk("%s:invalid argument\n",__func__);\r
- return -EINVAL;\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
- if(sensor->ops->ctrl_data != mode)\r
- {\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
- \r
- sensor->ops->ctrl_data = mode;\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:\r
- status = compass_akm_get_closestatus(); \r
- DBG("%s:closestatus=%d\n",__func__,status);\r
- break;\r
- case ECS_IOCTL_GET_DELAY:\r
- DBG("%s:ECS_IOCTL_GET_DELAY start\n",__func__);\r
- mutex_lock(&sensor->operation_mutex);\r
- delay[0] = sensor->flags.delay;\r
- delay[1] = sensor->flags.delay;\r
- delay[2] = sensor->flags.delay;\r
- mutex_unlock(&sensor->operation_mutex);\r
- break;\r
- \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
- case ECS_IOCTL_GET_LAYOUT:\r
- DBG("%s:ECS_IOCTL_GET_LAYOUT start\n",__func__);\r
+ if (*stat2 & 0x08)
+ {
+ DBG(KERN_ERR "%s:compass data overflow\n",__func__);
+ return -3;
+ }
+#endif
+ /* »¥³âµØ»º´æÊý¾Ý. */
+ mutex_lock(&sensor->data_mutex);
+ memcpy(sensor->sensor_data, buffer, sensor->ops->read_len);
+ mutex_unlock(&sensor->data_mutex);
+ DBG("%s:",__func__);
+ for(i=0; i<sensor->ops->read_len; i++)
+ DBG("0x%x,",buffer[i]);
+ DBG("\n");
+
+ 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);
+ }
+
+
+ //trigger next measurement
+ ret = sensor_write_reg(client, sensor->ops->ctrl_reg, sensor->ops->ctrl_data);
+ if(ret)
+ {
+ printk(KERN_ERR "%s:fail to set ctrl_data:0x%x\n",__func__,sensor->ops->ctrl_data);
+ return ret;
+ }
+
+ return ret;
+}
+
+static void compass_set_YPR(int *rbuf)
+{
+ struct sensor_private_data *sensor =
+ (struct sensor_private_data *) i2c_get_clientdata(this_client);
+
+ /* No events are reported */
+ if (!rbuf[0]) {
+ printk("%s:Don't waste a time.",__func__);
+ return;
+ }
+
+ DBG("%s:buf[0]=0x%x\n",__func__, rbuf[0]);
+
+ /* Report magnetic sensor information */
+ if (atomic_read(&sensor->flags.m_flag) && (rbuf[0] & ORI_DATA_READY)) {
+ input_report_abs(sensor->input_dev, ABS_RX, rbuf[9]);
+ input_report_abs(sensor->input_dev, ABS_RY, rbuf[10]);
+ input_report_abs(sensor->input_dev, ABS_RZ, rbuf[11]);
+ input_report_abs(sensor->input_dev, ABS_RUDDER, rbuf[4]);
+ DBG("%s:m_flag:x=%d,y=%d,z=%d,RUDDER=%d\n",__func__,rbuf[9], rbuf[10], rbuf[11], rbuf[4]);
+ }
+
+ /* Report acceleration sensor information */
+ if (atomic_read(&sensor->flags.a_flag) && (rbuf[0] & ACC_DATA_READY)) {
+ input_report_abs(sensor->input_dev, ABS_X, rbuf[1]);
+ input_report_abs(sensor->input_dev, ABS_Y, rbuf[2]);
+ input_report_abs(sensor->input_dev, ABS_Z, rbuf[3]);
+ input_report_abs(sensor->input_dev, ABS_WHEEL, rbuf[4]);
+
+ DBG("%s:a_flag:x=%d,y=%d,z=%d,WHEEL=%d\n",__func__,rbuf[1], rbuf[2], rbuf[3], rbuf[4]);
+ }
+
+ /* Report magnetic vector information */
+ if (atomic_read(&sensor->flags.mv_flag) && (rbuf[0] & MAG_DATA_READY)) {
+ input_report_abs(sensor->input_dev, ABS_HAT0X, rbuf[5]);
+ input_report_abs(sensor->input_dev, ABS_HAT0Y, rbuf[6]);
+ input_report_abs(sensor->input_dev, ABS_BRAKE, rbuf[7]);
+ input_report_abs(sensor->input_dev, ABS_HAT1X, rbuf[8]);
+
+ DBG("%s:mv_flag:x=%d,y=%d,z=%d,status=%d\n",__func__,rbuf[5], rbuf[6], rbuf[7], rbuf[8]);
+ }
+
+ input_sync(sensor->input_dev);
+
+ memcpy(g_akm_rbuf, rbuf, 12); //used for ECS_IOCTL_GET_ACCEL
+}
+
+
+
+static int compass_dev_open(struct inode *inode, struct file *file)
+{
+ struct sensor_private_data* sensor =
+ (struct sensor_private_data *)i2c_get_clientdata(this_client);
+ int result = 0;
+ DBG("%s\n",__func__);
+
+ return result;
+}
+
+
+static int compass_dev_release(struct inode *inode, struct file *file)
+{
+ struct sensor_private_data* sensor =
+ (struct sensor_private_data *)i2c_get_clientdata(this_client);
+ int result = 0;
+ DBG("%s\n",__func__);
+
+ return result;
+}
+
+static int compass_akm_set_mode(struct i2c_client *client, char mode)
+{
+ struct sensor_private_data* sensor = (struct sensor_private_data *)i2c_get_clientdata(this_client);
+ int result = 0;
+
+ switch(mode & 0x1f)
+ {
+ case AK09911_MODE_SNG_MEASURE:
+ case AK09911_MODE_SELF_TEST:
+ case AK09911_MODE_FUSE_ACCESS:
+ if(sensor->status_cur == SENSOR_OFF)
+ {
+ if(sensor->pdata->irq_enable)
+ {
+ //DBG("%s:enable irq=%d\n",__func__,client->irq);
+ //enable_irq(client->irq);
+ }
+ else
+ {
+ schedule_delayed_work(&sensor->delaywork, msecs_to_jiffies(sensor->pdata->poll_delay_ms));
+ }
+
+ sensor->status_cur = SENSOR_ON;
+ }
+
+ break;
+
+ case AK09911_MODE_POWERDOWN:
+ if(sensor->status_cur == SENSOR_ON)
+ {
+ if(sensor->pdata->irq_enable)
+ {
+ //DBG("%s:disable irq=%d\n",__func__,client->irq);
+ //disable_irq_nosync(client->irq);//disable irq
+ }
+ else
+ cancel_delayed_work_sync(&sensor->delaywork);
+
+ sensor->status_cur = SENSOR_OFF;
+ }
+ break;
+
+ }
+
+ switch(mode & 0x1f)
+ {
+ case AK09911_MODE_SNG_MEASURE:
+ result = sensor_write_reg(client, sensor->ops->ctrl_reg, AK09911_MODE_SNG_MEASURE);
+ if(result)
+ printk("%s:i2c error,mode=%d\n",__func__,mode);
+ break;
+ case AK09911_MODE_SELF_TEST:
+ result = sensor_write_reg(client, sensor->ops->ctrl_reg, AK09911_MODE_SELF_TEST);
+ if(result)
+ printk("%s:i2c error,mode=%d\n",__func__,mode);
+ break;
+ case AK09911_MODE_FUSE_ACCESS:
+ result = sensor_write_reg(client, sensor->ops->ctrl_reg, AK09911_MODE_FUSE_ACCESS);
+ if(result)
+ printk("%s:i2c error,mode=%d\n",__func__,mode);
+ break;
+ case AK09911_MODE_POWERDOWN:
+ /* Set powerdown mode */
+ result = sensor_write_reg(client, sensor->ops->ctrl_reg, AK09911_MODE_POWERDOWN);
+ if(result)
+ printk("%s:i2c error,mode=%d\n",__func__,mode);
+ udelay(100);
+ break;
+ default:
+ printk("%s: Unknown mode(%d)", __func__, mode);
+ result = -EINVAL;
+ break;
+ }
+ DBG("%s:mode=0x%x\n",__func__,mode);
+ return result;
+
+}
+
+static int compass_akm_reset(struct i2c_client *client)
+{
+ struct sensor_private_data* sensor = (struct sensor_private_data *)i2c_get_clientdata(this_client);
+ int result = 0;
+
+ if(sensor->pdata->reset_pin > 0)
+ {
+ gpio_direction_output(sensor->pdata->reset_pin, GPIO_LOW);
+ udelay(10);
+ gpio_direction_output(sensor->pdata->reset_pin, GPIO_HIGH);
+ }
+ else
+ {
+ /* Set measure mode */
+ result = sensor_write_reg(client, sensor->ops->ctrl_reg, AK09911_MODE_SNG_MEASURE);
+ if(result)
+ printk("%s:fail to Set measure mode\n",__func__);
+ }
+
+ udelay(100);
+
+ return result;
+
+}
+
+
+
+static int compass_akm_get_openstatus(void)
+{
+ struct sensor_private_data* sensor = (struct sensor_private_data *)i2c_get_clientdata(this_client);
+ wait_event_interruptible(sensor->flags.open_wq, (atomic_read(&sensor->flags.open_flag) != 0));
+ return atomic_read(&sensor->flags.open_flag);
+}
+
+static int compass_akm_get_closestatus(void)
+{
+ struct sensor_private_data* sensor = (struct sensor_private_data *)i2c_get_clientdata(this_client);
+ wait_event_interruptible(sensor->flags.open_wq, (atomic_read(&sensor->flags.open_flag) <= 0));
+ return atomic_read(&sensor->flags.open_flag);
+}
+
+
+/* ioctl - I/O control */
+static long compass_dev_ioctl(struct file *file,
+ unsigned int cmd, unsigned long arg)
+{
+ struct sensor_private_data* sensor = (struct sensor_private_data *)i2c_get_clientdata(this_client);
+ struct i2c_client *client = this_client;
+ void __user *argp = (void __user *)arg;
+ int result = 0;
+ struct akm_platform_data compass;
+
+ /* NOTE: In this function the size of "char" should be 1-byte. */
+ char compass_data[SENSOR_DATA_SIZE]; /* for GETDATA */
+ char rwbuf[RWBUF_SIZE]; /* for READ/WRITE */
+ char mode; /* for SET_MODE*/
+ int value[YPR_DATA_SIZE]; /* for SET_YPR */
+ int status; /* for OPEN/CLOSE_STATUS */
+ int ret = -1; /* Return value. */
+
+ //int8_t sensor_buf[SENSOR_DATA_SIZE]; /* for GETDATA */
+ //int32_t ypr_buf[YPR_DATA_SIZE]; /* for SET_YPR */
+ int16_t acc_buf[3]; /* for GET_ACCEL */
+ int64_t delay[AKM_NUM_SENSORS]; /* for GET_DELAY */
+ char layout; /* for GET_LAYOUT */
+ char outbit; /* for GET_OUTBIT */
+
+ switch (cmd) {
+ case ECS_IOCTL_WRITE:
+ case ECS_IOCTL_READ:
+ if (argp == NULL) {
+ return -EINVAL;
+ }
+ if (copy_from_user(&rwbuf, argp, sizeof(rwbuf))) {
+ return -EFAULT;
+ }
+ break;
+ case ECS_IOCTL_SET_MODE:
+ if (argp == NULL) {
+ return -EINVAL;
+ }
+ if (copy_from_user(&mode, argp, sizeof(mode))) {
+ return -EFAULT;
+ }
+ break;
+ case ECS_IOCTL_SET_YPR:
+ if (argp == NULL) {
+ return -EINVAL;
+ }
+ if (copy_from_user(&value, argp, sizeof(value))) {
+ return -EFAULT;
+ }
+ break;
+ case ECS_IOCTL_GETDATA:
+ case ECS_IOCTL_GET_OPEN_STATUS:
+ case ECS_IOCTL_GET_CLOSE_STATUS:
+ case ECS_IOCTL_GET_DELAY:
+ case ECS_IOCTL_GET_LAYOUT:
+ case ECS_IOCTL_GET_OUTBIT:
+ case ECS_IOCTL_GET_ACCEL:
+ case ECS_IOCTL_GET_INFO:
+ case ECS_IOCTL_GET_CONF:
+ /* Just check buffer pointer */
+ if (argp == NULL) {
+ printk("%s:invalid argument\n",__func__);
+ return -EINVAL;
+ }
+ break;
+ default:
+ break;
+ }
+
+ switch (cmd) {
+ case ECS_IOCTL_WRITE:
+ DBG("%s:ECS_IOCTL_WRITE start\n",__func__);
+ mutex_lock(&sensor->operation_mutex);
+ if ((rwbuf[0] < 2) || (rwbuf[0] > (RWBUF_SIZE-1))) {
+ mutex_unlock(&sensor->operation_mutex);
+ return -EINVAL;
+ }
+ ret = sensor_tx_data(client, &rwbuf[1], rwbuf[0]);
+ if (ret < 0) {
+ mutex_unlock(&sensor->operation_mutex);
+ printk("%s:fait to tx data\n",__func__);
+ return ret;
+ }
+ mutex_unlock(&sensor->operation_mutex);
+ break;
+ case ECS_IOCTL_READ:
+ DBG("%s:ECS_IOCTL_READ start\n",__func__);
+ mutex_lock(&sensor->operation_mutex);
+ if ((rwbuf[0] < 1) || (rwbuf[0] > (RWBUF_SIZE-1))) {
+ mutex_unlock(&sensor->operation_mutex);
+ printk("%s:data is error\n",__func__);
+ return -EINVAL;
+ }
+ ret = sensor_rx_data(client, &rwbuf[1], rwbuf[0]);
+ if (ret < 0) {
+ mutex_unlock(&sensor->operation_mutex);
+ printk("%s:fait to rx data\n",__func__);
+ return ret;
+ }
+ mutex_unlock(&sensor->operation_mutex);
+ break;
+ case ECS_IOCTL_SET_MODE:
+ DBG("%s:ECS_IOCTL_SET_MODE start\n",__func__);
+ mutex_lock(&sensor->operation_mutex);
+ if(sensor->ops->ctrl_data != mode)
+ {
+ ret = compass_akm_set_mode(client, mode);
+ if (ret < 0) {
+ printk("%s:fait to set mode\n",__func__);
+ mutex_unlock(&sensor->operation_mutex);
+ return ret;
+ }
+
+ sensor->ops->ctrl_data = mode;
+ }
+ mutex_unlock(&sensor->operation_mutex);
+ break;
+ case ECS_IOCTL_GETDATA:
+ DBG("%s:ECS_IOCTL_GETDATA start\n",__func__);
+ mutex_lock(&sensor->data_mutex);
+ memcpy(compass_data, sensor->sensor_data, SENSOR_DATA_SIZE); //get data from buffer
+ mutex_unlock(&sensor->data_mutex);
+ break;
+ case ECS_IOCTL_SET_YPR:
+ DBG("%s:ECS_IOCTL_SET_YPR start\n",__func__);
+ mutex_lock(&sensor->data_mutex);
+ compass_set_YPR(value);
+ mutex_unlock(&sensor->data_mutex);
+ break;
+ case ECS_IOCTL_GET_OPEN_STATUS:
+ status = compass_akm_get_openstatus();
+ DBG("%s:openstatus=%d\n",__func__,status);
+ break;
+ case ECS_IOCTL_GET_CLOSE_STATUS:
+ status = compass_akm_get_closestatus();
+ DBG("%s:closestatus=%d\n",__func__,status);
+ break;
+ case ECS_IOCTL_GET_DELAY:
+ DBG("%s:ECS_IOCTL_GET_DELAY start\n",__func__);
+ mutex_lock(&sensor->operation_mutex);
+ delay[0] = sensor->flags.delay;
+ delay[1] = sensor->flags.delay;
+ delay[2] = sensor->flags.delay;
+ mutex_unlock(&sensor->operation_mutex);
+ break;
+
+ case ECS_IOCTL_GET_PLATFORM_DATA:
+ DBG("%s:ECS_IOCTL_GET_PLATFORM_DATA start\n",__func__);
+ // memcpy(compass.m_layout, sensor->pdata->m_layout, sizeof(sensor->pdata->m_layout));
+ // memcpy(compass.project_name, sensor->pdata->project_name, sizeof(sensor->pdata->project_name));
+ ret = copy_to_user(argp, &compass, sizeof(compass));
+ if(ret < 0)
+ {
+ printk("%s:error,ret=%d\n",__FUNCTION__, ret);
+ return ret;
+ }
+ break;
+ case ECS_IOCTL_GET_LAYOUT:
+ DBG("%s:ECS_IOCTL_GET_LAYOUT start\n",__func__);
if((sensor->pdata->layout >= 1) && (sensor->pdata->layout <=8 ))
layout = sensor->pdata->layout;
else
layout = 1;
- break;\r
- case ECS_IOCTL_GET_OUTBIT:\r
- DBG("%s:ECS_IOCTL_GET_OUTBIT start\n",__func__);\r
- outbit = 1; //sensor->pdata->outbit;\r
- break;\r
- case ECS_IOCTL_RESET:\r
- DBG("%s:ECS_IOCTL_RESET start\n",__func__);\r
- ret = compass_akm_reset(client);\r
- if (ret < 0)\r
- return ret;\r
- break;\r
- case ECS_IOCTL_GET_ACCEL:\r
- DBG("%s:ECS_IOCTL_GET_ACCEL start,no accel data\n",__func__);\r
- mutex_lock(&sensor->operation_mutex);\r
- acc_buf[0] = g_akm_rbuf[6];\r
- acc_buf[1] = g_akm_rbuf[7];\r
- acc_buf[2] = g_akm_rbuf[8];\r
- mutex_unlock(&sensor->operation_mutex);\r
- break;\r
- case ECS_IOCTL_GET_INFO:\r
- ret = copy_to_user(argp, g_sensor_info, sizeof(g_sensor_info));\r
- if(ret < 0)\r
- {\r
- printk("%s:error,ret=%d\n",__FUNCTION__, ret);\r
- return ret;\r
- }\r
- break;\r
- case ECS_IOCTL_GET_CONF:\r
- ret = copy_to_user(argp, g_sensor_conf, sizeof(g_sensor_conf));\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
- case ECS_IOCTL_GET_LAYOUT:\r
- if (copy_to_user(argp, &layout, sizeof(layout))) {\r
- printk("%s:error:%d\n",__FUNCTION__,__LINE__);\r
- return -EFAULT;\r
- }\r
- break;\r
- case ECS_IOCTL_GET_OUTBIT:\r
- if (copy_to_user(argp, &outbit, sizeof(outbit))) {\r
- printk("%s:error:%d\n",__FUNCTION__,__LINE__);\r
- return -EFAULT;\r
- }\r
- break;\r
- case ECS_IOCTL_GET_ACCEL:\r
- if (copy_to_user(argp, &acc_buf, sizeof(acc_buf))) {\r
- printk("%s:error:%d\n",__FUNCTION__,__LINE__);\r
- return -EFAULT;\r
- }\r
- break;\r
- default:\r
- break;\r
- }\r
-\r
- return result;\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 = "akm_dev",\r
- .fops = &compass_dev_fops,\r
-};\r
-\r
-struct sensor_operate compass_akm09911_ops = {\r
- .name = "akm09911",\r
- .type = SENSOR_TYPE_COMPASS, //it is important\r
- .id_i2c = COMPASS_ID_AK09911,\r
- .read_reg = AK09911_REG_ST1, //read data\r
- .read_len = SENSOR_DATA_SIZE, //data length\r
- .id_reg = AK09911_REG_WIA2, //read id\r
- .id_data = AK09911_DEVICE_ID,\r
- .precision = 8, //12 bits\r
- .ctrl_reg = AK09911_REG_CNTL2, //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 = NULL, //private misc support\r
-};\r
-\r
-/****************operate according to sensor chip:end************/\r
-\r
-//function name should not be changed\r
-static struct sensor_operate *compass_get_ops(void)\r
-{\r
- return &compass_akm09911_ops; \r
-}\r
-\r
-\r
-static int __init compass_akm09911_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
- return result;\r
-}\r
-\r
-static void __exit compass_akm09911_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_akm09911_init);\r
-module_exit(compass_akm09911_exit);\r
-\r
-\r
+ break;
+ case ECS_IOCTL_GET_OUTBIT:
+ DBG("%s:ECS_IOCTL_GET_OUTBIT start\n",__func__);
+ outbit = 1; //sensor->pdata->outbit;
+ break;
+ case ECS_IOCTL_RESET:
+ DBG("%s:ECS_IOCTL_RESET start\n",__func__);
+ ret = compass_akm_reset(client);
+ if (ret < 0)
+ return ret;
+ break;
+ case ECS_IOCTL_GET_ACCEL:
+ DBG("%s:ECS_IOCTL_GET_ACCEL start,no accel data\n",__func__);
+ mutex_lock(&sensor->operation_mutex);
+ acc_buf[0] = g_akm_rbuf[6];
+ acc_buf[1] = g_akm_rbuf[7];
+ acc_buf[2] = g_akm_rbuf[8];
+ mutex_unlock(&sensor->operation_mutex);
+ break;
+ case ECS_IOCTL_GET_INFO:
+ ret = copy_to_user(argp, g_sensor_info, sizeof(g_sensor_info));
+ if(ret < 0)
+ {
+ printk("%s:error,ret=%d\n",__FUNCTION__, ret);
+ return ret;
+ }
+ break;
+ case ECS_IOCTL_GET_CONF:
+ ret = copy_to_user(argp, g_sensor_conf, sizeof(g_sensor_conf));
+ if(ret < 0)
+ {
+ printk("%s:error,ret=%d\n",__FUNCTION__, ret);
+ return ret;
+ }
+ break;
+
+ default:
+ return -ENOTTY;
+ }
+
+ switch (cmd) {
+ case ECS_IOCTL_READ:
+ if (copy_to_user(argp, &rwbuf, rwbuf[0]+1)) {
+ return -EFAULT;
+ }
+ break;
+ case ECS_IOCTL_GETDATA:
+ if (copy_to_user(argp, &compass_data, sizeof(compass_data))) {
+ return -EFAULT;
+ }
+ break;
+ case ECS_IOCTL_GET_OPEN_STATUS:
+ case ECS_IOCTL_GET_CLOSE_STATUS:
+ if (copy_to_user(argp, &status, sizeof(status))) {
+ return -EFAULT;
+ }
+ break;
+ case ECS_IOCTL_GET_DELAY:
+ if (copy_to_user(argp, &delay, sizeof(delay))) {
+ return -EFAULT;
+ }
+ break;
+ case ECS_IOCTL_GET_LAYOUT:
+ if (copy_to_user(argp, &layout, sizeof(layout))) {
+ printk("%s:error:%d\n",__FUNCTION__,__LINE__);
+ return -EFAULT;
+ }
+ break;
+ case ECS_IOCTL_GET_OUTBIT:
+ if (copy_to_user(argp, &outbit, sizeof(outbit))) {
+ printk("%s:error:%d\n",__FUNCTION__,__LINE__);
+ return -EFAULT;
+ }
+ break;
+ case ECS_IOCTL_GET_ACCEL:
+ if (copy_to_user(argp, &acc_buf, sizeof(acc_buf))) {
+ printk("%s:error:%d\n",__FUNCTION__,__LINE__);
+ return -EFAULT;
+ }
+ break;
+ default:
+ break;
+ }
+
+ return result;
+}
+
+static struct file_operations compass_dev_fops =
+{
+ .owner = THIS_MODULE,
+ .open = compass_dev_open,
+ .release = compass_dev_release,
+ .unlocked_ioctl = compass_dev_ioctl,
+};
+
+
+static struct miscdevice compass_dev_device =
+{
+ .minor = MISC_DYNAMIC_MINOR,
+ .name = "akm_dev",
+ .fops = &compass_dev_fops,
+};
+
+struct sensor_operate compass_akm09911_ops = {
+ .name = "akm09911",
+ .type = SENSOR_TYPE_COMPASS, //it is important
+ .id_i2c = COMPASS_ID_AK09911,
+ .read_reg = AK09911_REG_ST1, //read data
+ .read_len = SENSOR_DATA_SIZE, //data length
+ .id_reg = AK09911_REG_WIA2, //read id
+ .id_data = AK09911_DEVICE_ID,
+ .precision = 8, //12 bits
+ .ctrl_reg = AK09911_REG_CNTL2, //enable or disable
+ .int_status_reg = SENSOR_UNKNOW_DATA, //not exist
+ .range = {-0xffff,0xffff},
+ .trig = IRQF_TRIGGER_RISING, //if LEVEL interrupt then IRQF_ONESHOT
+ .active = sensor_active,
+ .init = sensor_init,
+ .report = sensor_report_value,
+ .misc_dev = NULL, //private misc support
+};
+
+/****************operate according to sensor chip:end************/
+
+//function name should not be changed
+static struct sensor_operate *compass_get_ops(void)
+{
+ return &compass_akm09911_ops;
+}
+
+
+static int __init compass_akm09911_init(void)
+{
+ struct sensor_operate *ops = compass_get_ops();
+ int result = 0;
+ int type = ops->type;
+ result = sensor_register_slave(type, NULL, NULL, compass_get_ops);
+
+ return result;
+}
+
+static void __exit compass_akm09911_exit(void)
+{
+ struct sensor_operate *ops = compass_get_ops();
+ int type = ops->type;
+ sensor_unregister_slave(type, NULL, NULL, compass_get_ops);
+}
+
+
+module_init(compass_akm09911_init);
+module_exit(compass_akm09911_exit);
+
+
-/* drivers/input/sensors/access/akm8963.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 <linux/of_gpio.h>\r
-#ifdef CONFIG_HAS_EARLYSUSPEND\r
-#include <linux/earlysuspend.h>\r
-#endif\r
-#include <linux/sensor-dev.h>\r
-\r
+/* drivers/input/sensors/access/akm8963.c
+ *
+ * Copyright (C) 2012-2015 ROCKCHIP.
+ * Author: luowei <lw@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>
+
#define AKM_SENSOR_INFO_SIZE 2
#define AKM_SENSOR_CONF_SIZE 3
-#define SENSOR_DATA_SIZE 8\r
-#define YPR_DATA_SIZE 12\r
-#define RWBUF_SIZE 16\r
-\r
-#define ACC_DATA_FLAG 0\r
-#define MAG_DATA_FLAG 1\r
-#define ORI_DATA_FLAG 2\r
-#define AKM_NUM_SENSORS 3\r
-\r
-#define ACC_DATA_READY (1<<(ACC_DATA_FLAG))\r
-#define MAG_DATA_READY (1<<(MAG_DATA_FLAG))\r
-#define ORI_DATA_READY (1<<(ORI_DATA_FLAG))\r
-\r
-/*! \name AK8963 constant definition\r
- \anchor AK8963_Def\r
- Constant definitions of the AK8963.*/\r
-#define AK8963_MEASUREMENT_TIME_US 10000\r
-\r
-/*! \name AK8963 operation mode\r
- \anchor AK8963_Mode\r
- Defines an operation mode of the AK8963.*/\r
-/*! @{*/\r
-#define AK8963_MODE_SNG_MEASURE 0x01\r
-#define AK8963_MODE_SELF_TEST 0x08\r
-#define AK8963_MODE_FUSE_ACCESS 0x0F\r
-#define AK8963_MODE_POWERDOWN 0x00\r
-\r
-/*! @}*/\r
-\r
-/*! \name AK8963 register address\r
-\anchor AK8963_REG\r
-Defines a register address of the AK8963.*/\r
-/*! @{*/\r
-#define AK8963_REG_WIA 0x00\r
-#define AK8963_REG_INFO 0x01\r
-#define AK8963_REG_ST1 0x02\r
-#define AK8963_REG_HXL 0x03\r
-#define AK8963_REG_HXH 0x04\r
-#define AK8963_REG_HYL 0x05\r
-#define AK8963_REG_HYH 0x06\r
-#define AK8963_REG_HZL 0x07\r
-#define AK8963_REG_HZH 0x08\r
-#define AK8963_REG_ST2 0x09\r
-#define AK8963_REG_CNTL1 0x0A\r
-#define AK8963_REG_CNTL2 0x0B\r
-#define AK8963_REG_ASTC 0x0C\r
-#define AK8963_REG_TS1 0x0D\r
-#define AK8963_REG_TS2 0x0E\r
-#define AK8963_REG_I2CDIS 0x0F\r
+#define SENSOR_DATA_SIZE 8
+#define YPR_DATA_SIZE 12
+#define RWBUF_SIZE 16
+
+#define ACC_DATA_FLAG 0
+#define MAG_DATA_FLAG 1
+#define ORI_DATA_FLAG 2
+#define AKM_NUM_SENSORS 3
+
+#define ACC_DATA_READY (1<<(ACC_DATA_FLAG))
+#define MAG_DATA_READY (1<<(MAG_DATA_FLAG))
+#define ORI_DATA_READY (1<<(ORI_DATA_FLAG))
+
+/*! \name AK8963 constant definition
+ \anchor AK8963_Def
+ Constant definitions of the AK8963.*/
+#define AK8963_MEASUREMENT_TIME_US 10000
+
+/*! \name AK8963 operation mode
+ \anchor AK8963_Mode
+ Defines an operation mode of the AK8963.*/
+/*! @{*/
+#define AK8963_MODE_SNG_MEASURE 0x01
+#define AK8963_MODE_SELF_TEST 0x08
+#define AK8963_MODE_FUSE_ACCESS 0x0F
+#define AK8963_MODE_POWERDOWN 0x00
+
+/*! @}*/
+
+/*! \name AK8963 register address
+\anchor AK8963_REG
+Defines a register address of the AK8963.*/
+/*! @{*/
+#define AK8963_REG_WIA 0x00
+#define AK8963_REG_INFO 0x01
+#define AK8963_REG_ST1 0x02
+#define AK8963_REG_HXL 0x03
+#define AK8963_REG_HXH 0x04
+#define AK8963_REG_HYL 0x05
+#define AK8963_REG_HYH 0x06
+#define AK8963_REG_HZL 0x07
+#define AK8963_REG_HZH 0x08
+#define AK8963_REG_ST2 0x09
+#define AK8963_REG_CNTL1 0x0A
+#define AK8963_REG_CNTL2 0x0B
+#define AK8963_REG_ASTC 0x0C
+#define AK8963_REG_TS1 0x0D
+#define AK8963_REG_TS2 0x0E
+#define AK8963_REG_I2CDIS 0x0F
#define AK8963_WIA_VALUE 0x48
-/*! @}*/\r
-\r
-/*! \name AK8963 fuse-rom address\r
-\anchor AK8963_FUSE\r
-Defines a read-only address of the fuse ROM of the AK8963.*/\r
-/*! @{*/\r
-#define AK8963_FUSE_ASAX 0x10\r
-#define AK8963_FUSE_ASAY 0x11\r
-#define AK8963_FUSE_ASAZ 0x12\r
-/*! @}*/\r
-\r
-#define AK8963_INFO_DATA (0x03<<3)\r
-\r
-\r
-#define COMPASS_IOCTL_MAGIC 'c'\r
-\r
-/* IOCTLs for AKM library */\r
-#define ECS_IOCTL_WRITE _IOW(COMPASS_IOCTL_MAGIC, 0x01, char*)\r
-#define ECS_IOCTL_READ _IOWR(COMPASS_IOCTL_MAGIC, 0x02, char*)\r
-#define ECS_IOCTL_RESET _IO(COMPASS_IOCTL_MAGIC, 0x03) /* NOT used in AK8975 */\r
-#define ECS_IOCTL_SET_MODE _IOW(COMPASS_IOCTL_MAGIC, 0x04, short)\r
-#define ECS_IOCTL_GETDATA _IOR(COMPASS_IOCTL_MAGIC, 0x05, char[SENSOR_DATA_SIZE])\r
-#define ECS_IOCTL_SET_YPR _IOW(COMPASS_IOCTL_MAGIC, 0x06, short[12])\r
-#define ECS_IOCTL_GET_OPEN_STATUS _IOR(COMPASS_IOCTL_MAGIC, 0x07, int)\r
-#define ECS_IOCTL_GET_CLOSE_STATUS _IOR(COMPASS_IOCTL_MAGIC, 0x08, int)\r
-#define ECS_IOCTL_GET_LAYOUT _IOR(COMPASS_IOCTL_MAGIC, 0x09, char)\r
-#define ECS_IOCTL_GET_ACCEL _IOR(COMPASS_IOCTL_MAGIC, 0x0A, short[3])\r
-#define ECS_IOCTL_GET_OUTBIT _IOR(COMPASS_IOCTL_MAGIC, 0x0B, char)\r
-#define ECS_IOCTL_GET_DELAY _IOR(COMPASS_IOCTL_MAGIC, 0x30, short)\r
-#define ECS_IOCTL_GET_PROJECT_NAME _IOR(COMPASS_IOCTL_MAGIC, 0x0D, char[64])\r
-#define ECS_IOCTL_GET_MATRIX _IOR(COMPASS_IOCTL_MAGIC, 0x0E, short [4][3][3])\r
-#define ECS_IOCTL_GET_PLATFORM_DATA _IOR(COMPASS_IOCTL_MAGIC, 0x0E, struct akm_platform_data)\r
+/*! @}*/
+
+/*! \name AK8963 fuse-rom address
+\anchor AK8963_FUSE
+Defines a read-only address of the fuse ROM of the AK8963.*/
+/*! @{*/
+#define AK8963_FUSE_ASAX 0x10
+#define AK8963_FUSE_ASAY 0x11
+#define AK8963_FUSE_ASAZ 0x12
+/*! @}*/
+
+#define AK8963_INFO_DATA (0x03<<3)
+
+
+#define COMPASS_IOCTL_MAGIC 'c'
+
+/* IOCTLs for AKM library */
+#define ECS_IOCTL_WRITE _IOW(COMPASS_IOCTL_MAGIC, 0x01, char*)
+#define ECS_IOCTL_READ _IOWR(COMPASS_IOCTL_MAGIC, 0x02, char*)
+#define ECS_IOCTL_RESET _IO(COMPASS_IOCTL_MAGIC, 0x03) /* NOT used in AK8975 */
+#define ECS_IOCTL_SET_MODE _IOW(COMPASS_IOCTL_MAGIC, 0x04, short)
+#define ECS_IOCTL_GETDATA _IOR(COMPASS_IOCTL_MAGIC, 0x05, char[SENSOR_DATA_SIZE])
+#define ECS_IOCTL_SET_YPR _IOW(COMPASS_IOCTL_MAGIC, 0x06, short[12])
+#define ECS_IOCTL_GET_OPEN_STATUS _IOR(COMPASS_IOCTL_MAGIC, 0x07, int)
+#define ECS_IOCTL_GET_CLOSE_STATUS _IOR(COMPASS_IOCTL_MAGIC, 0x08, int)
+#define ECS_IOCTL_GET_LAYOUT _IOR(COMPASS_IOCTL_MAGIC, 0x09, char)
+#define ECS_IOCTL_GET_ACCEL _IOR(COMPASS_IOCTL_MAGIC, 0x0A, short[3])
+#define ECS_IOCTL_GET_OUTBIT _IOR(COMPASS_IOCTL_MAGIC, 0x0B, char)
+#define ECS_IOCTL_GET_DELAY _IOR(COMPASS_IOCTL_MAGIC, 0x30, short)
+#define ECS_IOCTL_GET_PROJECT_NAME _IOR(COMPASS_IOCTL_MAGIC, 0x0D, char[64])
+#define ECS_IOCTL_GET_MATRIX _IOR(COMPASS_IOCTL_MAGIC, 0x0E, short [4][3][3])
+#define ECS_IOCTL_GET_PLATFORM_DATA _IOR(COMPASS_IOCTL_MAGIC, 0x0E, struct akm_platform_data)
#define ECS_IOCTL_GET_INFO _IOR(COMPASS_IOCTL_MAGIC, 0x27, unsigned char[AKM_SENSOR_INFO_SIZE])
#define ECS_IOCTL_GET_CONF _IOR(COMPASS_IOCTL_MAGIC, 0x28, unsigned char[AKM_SENSOR_CONF_SIZE])
-\r
-#define AK8963_DEVICE_ID 0x48\r
-static struct i2c_client *this_client;\r
-static struct miscdevice compass_dev_device;\r
-\r
-static short g_akm_rbuf[12];\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
- \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
- sensor->ops->ctrl_data = AK8963_MODE_SNG_MEASURE; \r
- }\r
- else\r
- {\r
- sensor->ops->ctrl_data = AK8963_MODE_POWERDOWN;\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
- char info = 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
- info = sensor_read_reg(client, AK8963_REG_INFO); \r
- if((info & (0x0f<<3)) != AK8963_INFO_DATA)\r
- {\r
- printk("%s:info=0x%x,it is not %s\n",__func__, info, sensor->ops->name);\r
- return -1;\r
- }\r
-\r
- result = misc_register(&compass_dev_device);\r
- if (result < 0) {\r
- printk("%s:fail to register misc device %s\n", __func__, compass_dev_device.name);\r
- result = -1;\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
- char value = 0;\r
- int i;\r
-\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
+
+#define AK8963_DEVICE_ID 0x48
+static struct i2c_client *this_client;
+static struct miscdevice compass_dev_device;
+
+static short g_akm_rbuf[12];
+
+
+/****************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;
+
+ //sensor->ops->ctrl_data = sensor_read_reg(client, sensor->ops->ctrl_reg);
+
+ //register setting according to chip datasheet
+ if(enable)
+ {
+ sensor->ops->ctrl_data = AK8963_MODE_SNG_MEASURE;
+ }
+ else
+ {
+ sensor->ops->ctrl_data = AK8963_MODE_POWERDOWN;
+ }
+
+ 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;
+ char info = 0;
+
+ this_client = client;
+
+ result = sensor->ops->active(client,0,0);
+ if(result)
+ {
+ printk("%s:line=%d,error\n",__func__,__LINE__);
+ return result;
+ }
+
+ sensor->status_cur = SENSOR_OFF;
+
+ info = sensor_read_reg(client, AK8963_REG_INFO);
+ if((info & (0x0f<<3)) != AK8963_INFO_DATA)
+ {
+ printk("%s:info=0x%x,it is not %s\n",__func__, info, sensor->ops->name);
+ return -1;
+ }
+
+ result = misc_register(&compass_dev_device);
+ if (result < 0) {
+ printk("%s:fail to register misc device %s\n", __func__, compass_dev_device.name);
+ result = -1;
+ }
+
+ DBG("%s:status_cur=%d\n",__func__, sensor->status_cur);
+ return result;
+}
+
+static int sensor_report_value(struct i2c_client *client)
+{
+ struct sensor_private_data *sensor =
+ (struct sensor_private_data *) i2c_get_clientdata(client);
+ char buffer[8] = {0};
+ unsigned char *stat;
+ unsigned char *stat2;
+ int ret = 0;
+ char value = 0;
+ int i;
+
+ if(sensor->ops->read_len < 8) //sensor->ops->read_len = 8
+ {
+ 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);
+
+ stat = &buffer[0];
+ stat2 = &buffer[7];
+
+ /*
* 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
+ */
+ if ((*stat & 0x01) != 0x01) {
+ DBG(KERN_ERR "%s:ST is not set\n",__func__);
+ return -1;
+ }
/*
* ST2 : data error -
* 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
+ if (*stat2 & 0x04)
+ {
+ DBG(KERN_ERR "%s:compass data error\n",__func__);
+ return -2;
+ }
+
/*
* ST2 : overflow -
* the sum of the absolute values of all axis |X|+|Y|+|Z| < 2400uT.
* 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
- DBG("%s:",__func__);\r
- for(i=0; i<sensor->ops->read_len; i++)\r
- DBG("0x%x,",buffer[i]);\r
- DBG("\n");\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
- \r
- //trigger next measurement \r
- ret = sensor_write_reg(client, sensor->ops->ctrl_reg, sensor->ops->ctrl_data);\r
- if(ret)\r
- {\r
- printk(KERN_ERR "%s:fail to set ctrl_data:0x%x\n",__func__,sensor->ops->ctrl_data);\r
- return ret;\r
- }\r
-\r
- return ret;\r
-}\r
-\r
-static void compass_set_YPR(int *rbuf)\r
-{\r
- struct sensor_private_data *sensor =\r
- (struct sensor_private_data *) i2c_get_clientdata(this_client); \r
-\r
- /* No events are reported */\r
- if (!rbuf[0]) {\r
- printk("%s:Don't waste a time.",__func__);\r
- return;\r
- }\r
-\r
- DBG("%s:buf[0]=0x%x\n",__func__, rbuf[0]);\r
- \r
- /* Report magnetic sensor information */\r
+ if (*stat2 & 0x08)
+ {
+ DBG(KERN_ERR "%s:compass data overflow\n",__func__);
+ return -3;
+ }
+
+ /* »¥³âµØ»º´æÊý¾Ý. */
+ mutex_lock(&sensor->data_mutex);
+ memcpy(sensor->sensor_data, buffer, sensor->ops->read_len);
+ mutex_unlock(&sensor->data_mutex);
+ DBG("%s:",__func__);
+ for(i=0; i<sensor->ops->read_len; i++)
+ DBG("0x%x,",buffer[i]);
+ DBG("\n");
+
+ 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);
+ }
+
+
+ //trigger next measurement
+ ret = sensor_write_reg(client, sensor->ops->ctrl_reg, sensor->ops->ctrl_data);
+ if(ret)
+ {
+ printk(KERN_ERR "%s:fail to set ctrl_data:0x%x\n",__func__,sensor->ops->ctrl_data);
+ return ret;
+ }
+
+ return ret;
+}
+
+static void compass_set_YPR(int *rbuf)
+{
+ struct sensor_private_data *sensor =
+ (struct sensor_private_data *) i2c_get_clientdata(this_client);
+
+ /* No events are reported */
+ if (!rbuf[0]) {
+ printk("%s:Don't waste a time.",__func__);
+ return;
+ }
+
+ DBG("%s:buf[0]=0x%x\n",__func__, rbuf[0]);
+
+ /* Report magnetic sensor information */
if (atomic_read(&sensor->flags.m_flag) && (rbuf[0] & ORI_DATA_READY)) {
input_report_abs(sensor->input_dev, ABS_RX, rbuf[9]);
input_report_abs(sensor->input_dev, ABS_RY, rbuf[10]);
input_report_abs(sensor->input_dev, ABS_RUDDER, rbuf[4]);
DBG("%s:m_flag:x=%d,y=%d,z=%d,RUDDER=%d\n", __func__, rbuf[9], rbuf[10], rbuf[11], rbuf[4]);
}
- \r
- /* Report acceleration sensor information */\r
- if (atomic_read(&sensor->flags.a_flag) && (rbuf[0] & ACC_DATA_READY)) {\r
- input_report_abs(sensor->input_dev, ABS_X, rbuf[1]);\r
- input_report_abs(sensor->input_dev, ABS_Y, rbuf[2]);\r
- input_report_abs(sensor->input_dev, ABS_Z, rbuf[3]);\r
- input_report_abs(sensor->input_dev, ABS_WHEEL, rbuf[4]);\r
- \r
- DBG("%s:a_flag:x=%d,y=%d,z=%d,WHEEL=%d\n",__func__,rbuf[1], rbuf[2], rbuf[3], rbuf[4]);\r
- }\r
- \r
- /* Report magnetic vector information */\r
+
+ /* Report acceleration sensor information */
+ if (atomic_read(&sensor->flags.a_flag) && (rbuf[0] & ACC_DATA_READY)) {
+ input_report_abs(sensor->input_dev, ABS_X, rbuf[1]);
+ input_report_abs(sensor->input_dev, ABS_Y, rbuf[2]);
+ input_report_abs(sensor->input_dev, ABS_Z, rbuf[3]);
+ input_report_abs(sensor->input_dev, ABS_WHEEL, rbuf[4]);
+
+ DBG("%s:a_flag:x=%d,y=%d,z=%d,WHEEL=%d\n",__func__,rbuf[1], rbuf[2], rbuf[3], rbuf[4]);
+ }
+
+ /* Report magnetic vector information */
if (atomic_read(&sensor->flags.mv_flag) && (rbuf[0] & MAG_DATA_READY)) {
input_report_abs(sensor->input_dev, ABS_HAT0X, rbuf[5]);
input_report_abs(sensor->input_dev, ABS_HAT0Y, rbuf[6]);
DBG("%s:mv_flag:x=%d,y=%d,z=%d,status=%d\n", __func__, rbuf[5], rbuf[6], rbuf[7], rbuf[8]);
}
- \r
- input_sync(sensor->input_dev);\r
-\r
- memcpy(g_akm_rbuf, rbuf, 12); //used for ECS_IOCTL_GET_ACCEL\r
-}\r
-\r
-\r
-\r
-static int compass_dev_open(struct inode *inode, struct file *file)\r
-{\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
- 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 & 0x0f)\r
- {\r
- case AK8963_MODE_SNG_MEASURE:\r
- case AK8963_MODE_SELF_TEST: \r
- case AK8963_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 AK8963_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 & 0x0f)\r
- {\r
- case AK8963_MODE_SNG_MEASURE: \r
- result = sensor_write_reg(client, sensor->ops->ctrl_reg, mode);\r
- if(result)\r
- printk("%s:i2c error,mode=%d\n",__func__,mode); \r
- break;\r
- case AK8963_MODE_SELF_TEST: \r
- result = sensor_write_reg(client, sensor->ops->ctrl_reg, mode);\r
- if(result)\r
- printk("%s:i2c error,mode=%d\n",__func__,mode);\r
- break;\r
- case AK8963_MODE_FUSE_ACCESS:\r
- result = sensor_write_reg(client, sensor->ops->ctrl_reg, mode);\r
- if(result)\r
- printk("%s:i2c error,mode=%d\n",__func__,mode);\r
- break;\r
- case AK8963_MODE_POWERDOWN:\r
- /* Set powerdown mode */\r
- result = sensor_write_reg(client, sensor->ops->ctrl_reg, AK8963_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=0x%x\n",__func__,mode);\r
- return result;\r
-\r
-}\r
-\r
-static int compass_akm_reset(struct i2c_client *client)\r
-{\r
- struct sensor_private_data* sensor = (struct sensor_private_data *)i2c_get_clientdata(this_client); \r
- int result = 0; \r
- \r
- if(sensor->pdata->reset_pin > 0)\r
- {\r
- gpio_direction_output(sensor->pdata->reset_pin, GPIO_LOW);\r
- udelay(10);\r
- gpio_direction_output(sensor->pdata->reset_pin, GPIO_HIGH);\r
- }\r
- else \r
- {\r
- /* Set measure mode */\r
- result = sensor_write_reg(client, AK8963_REG_CNTL2, AK8963_MODE_SNG_MEASURE);\r
- if(result)\r
- printk("%s:fail to Set measure mode\n",__func__);\r
- }\r
- \r
- udelay(100);\r
- \r
- return result;\r
-\r
-}\r
-\r
-\r
-\r
-static int compass_akm_get_openstatus(void)\r
-{ \r
- struct sensor_private_data* sensor = (struct sensor_private_data *)i2c_get_clientdata(this_client); \r
- wait_event_interruptible(sensor->flags.open_wq, (atomic_read(&sensor->flags.open_flag) != 0));\r
- return atomic_read(&sensor->flags.open_flag);\r
-}\r
-\r
-static int compass_akm_get_closestatus(void)\r
-{ \r
- struct sensor_private_data* sensor = (struct sensor_private_data *)i2c_get_clientdata(this_client); \r
- wait_event_interruptible(sensor->flags.open_wq, (atomic_read(&sensor->flags.open_flag) <= 0));\r
- return atomic_read(&sensor->flags.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 akm_platform_data compass;\r
+
+ input_sync(sensor->input_dev);
+
+ memcpy(g_akm_rbuf, rbuf, 12); //used for ECS_IOCTL_GET_ACCEL
+}
+
+
+
+static int compass_dev_open(struct inode *inode, struct file *file)
+{
+ int result = 0;
+ DBG("%s\n",__func__);
+
+ return result;
+}
+
+
+static int compass_dev_release(struct inode *inode, struct file *file)
+{
+ int result = 0;
+ DBG("%s\n",__func__);
+
+ return result;
+}
+
+static int compass_akm_set_mode(struct i2c_client *client, char mode)
+{
+ struct sensor_private_data* sensor = (struct sensor_private_data *)i2c_get_clientdata(this_client);
+ int result = 0;
+
+ switch(mode & 0x0f)
+ {
+ case AK8963_MODE_SNG_MEASURE:
+ case AK8963_MODE_SELF_TEST:
+ case AK8963_MODE_FUSE_ACCESS:
+ if(sensor->status_cur == SENSOR_OFF)
+ {
+ if(sensor->pdata->irq_enable)
+ {
+ //DBG("%s:enable irq=%d\n",__func__,client->irq);
+ //enable_irq(client->irq);
+ }
+ else
+ {
+ schedule_delayed_work(&sensor->delaywork, msecs_to_jiffies(sensor->pdata->poll_delay_ms));
+ }
+
+ sensor->status_cur = SENSOR_ON;
+ }
+
+ break;
+
+ case AK8963_MODE_POWERDOWN:
+ if(sensor->status_cur == SENSOR_ON)
+ {
+ if(sensor->pdata->irq_enable)
+ {
+ //DBG("%s:disable irq=%d\n",__func__,client->irq);
+ //disable_irq_nosync(client->irq);//disable irq
+ }
+ else
+ cancel_delayed_work_sync(&sensor->delaywork);
+
+ sensor->status_cur = SENSOR_OFF;
+ }
+ break;
+
+ }
+
+ switch(mode & 0x0f)
+ {
+ case AK8963_MODE_SNG_MEASURE:
+ result = sensor_write_reg(client, sensor->ops->ctrl_reg, mode);
+ if(result)
+ printk("%s:i2c error,mode=%d\n",__func__,mode);
+ break;
+ case AK8963_MODE_SELF_TEST:
+ result = sensor_write_reg(client, sensor->ops->ctrl_reg, mode);
+ if(result)
+ printk("%s:i2c error,mode=%d\n",__func__,mode);
+ break;
+ case AK8963_MODE_FUSE_ACCESS:
+ result = sensor_write_reg(client, sensor->ops->ctrl_reg, mode);
+ if(result)
+ printk("%s:i2c error,mode=%d\n",__func__,mode);
+ break;
+ case AK8963_MODE_POWERDOWN:
+ /* Set powerdown mode */
+ result = sensor_write_reg(client, sensor->ops->ctrl_reg, AK8963_MODE_POWERDOWN);
+ if(result)
+ printk("%s:i2c error,mode=%d\n",__func__,mode);
+ udelay(100);
+ break;
+ default:
+ printk("%s: Unknown mode(%d)", __func__, mode);
+ result = -EINVAL;
+ break;
+ }
+ DBG("%s:mode=0x%x\n",__func__,mode);
+ return result;
+
+}
+
+static int compass_akm_reset(struct i2c_client *client)
+{
+ struct sensor_private_data* sensor = (struct sensor_private_data *)i2c_get_clientdata(this_client);
+ int result = 0;
+
+ if(sensor->pdata->reset_pin > 0)
+ {
+ gpio_direction_output(sensor->pdata->reset_pin, GPIO_LOW);
+ udelay(10);
+ gpio_direction_output(sensor->pdata->reset_pin, GPIO_HIGH);
+ }
+ else
+ {
+ /* Set measure mode */
+ result = sensor_write_reg(client, AK8963_REG_CNTL2, AK8963_MODE_SNG_MEASURE);
+ if(result)
+ printk("%s:fail to Set measure mode\n",__func__);
+ }
+
+ udelay(100);
+
+ return result;
+
+}
+
+
+
+static int compass_akm_get_openstatus(void)
+{
+ struct sensor_private_data* sensor = (struct sensor_private_data *)i2c_get_clientdata(this_client);
+ wait_event_interruptible(sensor->flags.open_wq, (atomic_read(&sensor->flags.open_flag) != 0));
+ return atomic_read(&sensor->flags.open_flag);
+}
+
+static int compass_akm_get_closestatus(void)
+{
+ struct sensor_private_data* sensor = (struct sensor_private_data *)i2c_get_clientdata(this_client);
+ wait_event_interruptible(sensor->flags.open_wq, (atomic_read(&sensor->flags.open_flag) <= 0));
+ return atomic_read(&sensor->flags.open_flag);
+}
+
+
+/* ioctl - I/O control */
+static long compass_dev_ioctl(struct file *file,
+ unsigned int cmd, unsigned long arg)
+{
+ struct sensor_private_data* sensor = (struct sensor_private_data *)i2c_get_clientdata(this_client);
+ struct i2c_client *client = this_client;
+ void __user *argp = (void __user *)arg;
+ int result = 0;
+ struct akm_platform_data compass;
unsigned char sense_info[AKM_SENSOR_INFO_SIZE];
unsigned char sense_conf[AKM_SENSOR_CONF_SIZE];
- /* 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
- int value[12]; /* for SET_YPR */\r
- int status; /* for OPEN/CLOSE_STATUS */\r
- int ret = -1; /* Return value. */\r
- \r
- //int8_t sensor_buf[SENSOR_DATA_SIZE]; /* for GETDATA */\r
- //int32_t ypr_buf[YPR_DATA_SIZE]; /* for SET_YPR */\r
- int16_t acc_buf[3]; /* for GET_ACCEL */\r
- int64_t delay[AKM_NUM_SENSORS]; /* for GET_DELAY */\r
-\r
- char layout; /* for GET_LAYOUT */\r
- char outbit; /* for GET_OUTBIT */\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
+ /* NOTE: In this function the size of "char" should be 1-byte. */
+ char compass_data[SENSOR_DATA_SIZE]; /* for GETDATA */
+ char rwbuf[RWBUF_SIZE]; /* for READ/WRITE */
+ char mode; /* for SET_MODE*/
+ int value[12]; /* for SET_YPR */
+ int status; /* for OPEN/CLOSE_STATUS */
+ int ret = -1; /* Return value. */
+
+ //int8_t sensor_buf[SENSOR_DATA_SIZE]; /* for GETDATA */
+ //int32_t ypr_buf[YPR_DATA_SIZE]; /* for SET_YPR */
+ int16_t acc_buf[3]; /* for GET_ACCEL */
+ int64_t delay[AKM_NUM_SENSORS]; /* for GET_DELAY */
+
+ char layout; /* for GET_LAYOUT */
+ char outbit; /* for GET_OUTBIT */
+
+ switch (cmd) {
+ case ECS_IOCTL_WRITE:
+ case ECS_IOCTL_READ:
+ if (argp == NULL) {
+ return -EINVAL;
+ }
+ if (copy_from_user(&rwbuf, argp, sizeof(rwbuf))) {
+ return -EFAULT;
+ }
+ break;
+ case ECS_IOCTL_SET_MODE:
+ if (argp == NULL) {
+ return -EINVAL;
+ }
+ if (copy_from_user(&mode, argp, sizeof(mode))) {
+ return -EFAULT;
+ }
+ break;
+ case ECS_IOCTL_SET_YPR:
+ if (argp == NULL) {
+ return -EINVAL;
+ }
+ if (copy_from_user(&value, argp, sizeof(value))) {
+ return -EFAULT;
+ }
+ break;
case ECS_IOCTL_GET_INFO:
case ECS_IOCTL_GET_CONF:
- case ECS_IOCTL_GETDATA:\r
- case ECS_IOCTL_GET_OPEN_STATUS:\r
- case ECS_IOCTL_GET_CLOSE_STATUS:\r
- case ECS_IOCTL_GET_DELAY:\r
- case ECS_IOCTL_GET_LAYOUT:\r
- case ECS_IOCTL_GET_OUTBIT:\r
- case ECS_IOCTL_GET_ACCEL:\r
- /* Just check buffer pointer */\r
- if (argp == NULL) {\r
- printk("%s:invalid argument\n",__func__);\r
- return -EINVAL;\r
- }\r
- break;\r
- default:\r
- break;\r
- }\r
-\r
- switch (cmd) {\r
+ case ECS_IOCTL_GETDATA:
+ case ECS_IOCTL_GET_OPEN_STATUS:
+ case ECS_IOCTL_GET_CLOSE_STATUS:
+ case ECS_IOCTL_GET_DELAY:
+ case ECS_IOCTL_GET_LAYOUT:
+ case ECS_IOCTL_GET_OUTBIT:
+ case ECS_IOCTL_GET_ACCEL:
+ /* Just check buffer pointer */
+ if (argp == NULL) {
+ printk("%s:invalid argument\n",__func__);
+ return -EINVAL;
+ }
+ break;
+ default:
+ break;
+ }
+
+ switch (cmd) {
case ECS_IOCTL_GET_INFO:
sense_info[0] = AK8963_REG_WIA;
mutex_lock(&sensor->operation_mutex);
return ret;
}
break;
- 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
- if(sensor->ops->ctrl_data != mode)\r
- {\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
- \r
- sensor->ops->ctrl_data = mode;\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:\r
- status = compass_akm_get_closestatus(); \r
- DBG("%s:closestatus=%d\n",__func__,status);\r
- break;\r
- case ECS_IOCTL_GET_DELAY:\r
- DBG("%s:ECS_IOCTL_GET_DELAY start\n",__func__);\r
- mutex_lock(&sensor->operation_mutex);\r
- delay[0] = sensor->flags.delay;\r
- delay[1] = sensor->flags.delay;\r
- delay[2] = sensor->flags.delay;\r
- mutex_unlock(&sensor->operation_mutex);\r
- break;\r
- \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
- case ECS_IOCTL_GET_LAYOUT:\r
- DBG("%s:ECS_IOCTL_GET_LAYOUT start\n",__func__);\r
- layout = sensor->pdata->layout;\r
- break;\r
- case ECS_IOCTL_GET_OUTBIT:\r
- DBG("%s:ECS_IOCTL_GET_OUTBIT start\n",__func__);\r
- outbit = 1; //sensor->pdata->outbit;\r
- break;\r
- case ECS_IOCTL_RESET:\r
- DBG("%s:ECS_IOCTL_RESET start\n",__func__);\r
- ret = compass_akm_reset(client);\r
- if (ret < 0)\r
- return ret;\r
- break;\r
- case ECS_IOCTL_GET_ACCEL:\r
- DBG("%s:ECS_IOCTL_GET_ACCEL start,no accel data\n",__func__);\r
- mutex_lock(&sensor->operation_mutex);\r
- acc_buf[0] = g_akm_rbuf[6];\r
- acc_buf[1] = g_akm_rbuf[7];\r
- acc_buf[2] = g_akm_rbuf[8];\r
- mutex_unlock(&sensor->operation_mutex);\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
- case ECS_IOCTL_GET_LAYOUT:\r
- if (copy_to_user(argp, &layout, sizeof(layout))) {\r
- printk("%s:error:%d\n",__FUNCTION__,__LINE__);\r
- return -EFAULT;\r
- }\r
- break;\r
- case ECS_IOCTL_GET_OUTBIT:\r
- if (copy_to_user(argp, &outbit, sizeof(outbit))) {\r
- printk("%s:error:%d\n",__FUNCTION__,__LINE__);\r
- return -EFAULT;\r
- }\r
- break;\r
- case ECS_IOCTL_GET_ACCEL:\r
- if (copy_to_user(argp, &acc_buf, sizeof(acc_buf))) {\r
- printk("%s:error:%d\n",__FUNCTION__,__LINE__);\r
- return -EFAULT;\r
- }\r
- break;\r
+ case ECS_IOCTL_WRITE:
+ DBG("%s:ECS_IOCTL_WRITE start\n",__func__);
+ mutex_lock(&sensor->operation_mutex);
+ if ((rwbuf[0] < 2) || (rwbuf[0] > (RWBUF_SIZE-1))) {
+ mutex_unlock(&sensor->operation_mutex);
+ return -EINVAL;
+ }
+ ret = sensor_tx_data(client, &rwbuf[1], rwbuf[0]);
+ if (ret < 0) {
+ mutex_unlock(&sensor->operation_mutex);
+ printk("%s:fait to tx data\n",__func__);
+ return ret;
+ }
+ mutex_unlock(&sensor->operation_mutex);
+ break;
+ case ECS_IOCTL_READ:
+ DBG("%s:ECS_IOCTL_READ start\n",__func__);
+ mutex_lock(&sensor->operation_mutex);
+ if ((rwbuf[0] < 1) || (rwbuf[0] > (RWBUF_SIZE-1))) {
+ mutex_unlock(&sensor->operation_mutex);
+ printk("%s:data is error\n",__func__);
+ return -EINVAL;
+ }
+ ret = sensor_rx_data(client, &rwbuf[1], rwbuf[0]);
+ if (ret < 0) {
+ mutex_unlock(&sensor->operation_mutex);
+ printk("%s:fait to rx data\n",__func__);
+ return ret;
+ }
+ mutex_unlock(&sensor->operation_mutex);
+ break;
+ case ECS_IOCTL_SET_MODE:
+ DBG("%s:ECS_IOCTL_SET_MODE start\n",__func__);
+ mutex_lock(&sensor->operation_mutex);
+ if(sensor->ops->ctrl_data != mode)
+ {
+ ret = compass_akm_set_mode(client, mode);
+ if (ret < 0) {
+ printk("%s:fait to set mode\n",__func__);
+ mutex_unlock(&sensor->operation_mutex);
+ return ret;
+ }
+
+ sensor->ops->ctrl_data = mode;
+ }
+ mutex_unlock(&sensor->operation_mutex);
+ break;
+ case ECS_IOCTL_GETDATA:
+ DBG("%s:ECS_IOCTL_GETDATA start\n",__func__);
+ mutex_lock(&sensor->data_mutex);
+ memcpy(compass_data, sensor->sensor_data, SENSOR_DATA_SIZE); //get data from buffer
+ mutex_unlock(&sensor->data_mutex);
+ break;
+ case ECS_IOCTL_SET_YPR:
+ DBG("%s:ECS_IOCTL_SET_YPR start\n",__func__);
+ mutex_lock(&sensor->data_mutex);
+ compass_set_YPR(value);
+ mutex_unlock(&sensor->data_mutex);
+ break;
+ case ECS_IOCTL_GET_OPEN_STATUS:
+ status = compass_akm_get_openstatus();
+ DBG("%s:openstatus=%d\n",__func__,status);
+ break;
+ case ECS_IOCTL_GET_CLOSE_STATUS:
+ status = compass_akm_get_closestatus();
+ DBG("%s:closestatus=%d\n",__func__,status);
+ break;
+ case ECS_IOCTL_GET_DELAY:
+ DBG("%s:ECS_IOCTL_GET_DELAY start\n",__func__);
+ mutex_lock(&sensor->operation_mutex);
+ delay[0] = sensor->flags.delay;
+ delay[1] = sensor->flags.delay;
+ delay[2] = sensor->flags.delay;
+ mutex_unlock(&sensor->operation_mutex);
+ break;
+
+ case ECS_IOCTL_GET_PLATFORM_DATA:
+ DBG("%s:ECS_IOCTL_GET_PLATFORM_DATA start\n",__func__);
+ //memcpy(compass.m_layout, sensor->pdata->m_layout, sizeof(sensor->pdata->m_layout));
+ //memcpy(compass.project_name, sensor->pdata->project_name, sizeof(sensor->pdata->project_name));
+ ret = copy_to_user(argp, &compass, sizeof(compass));
+ if(ret < 0)
+ {
+ printk("%s:error,ret=%d\n",__FUNCTION__, ret);
+ return ret;
+ }
+ break;
+ case ECS_IOCTL_GET_LAYOUT:
+ DBG("%s:ECS_IOCTL_GET_LAYOUT start\n",__func__);
+ layout = sensor->pdata->layout;
+ break;
+ case ECS_IOCTL_GET_OUTBIT:
+ DBG("%s:ECS_IOCTL_GET_OUTBIT start\n",__func__);
+ outbit = 1; //sensor->pdata->outbit;
+ break;
+ case ECS_IOCTL_RESET:
+ DBG("%s:ECS_IOCTL_RESET start\n",__func__);
+ ret = compass_akm_reset(client);
+ if (ret < 0)
+ return ret;
+ break;
+ case ECS_IOCTL_GET_ACCEL:
+ DBG("%s:ECS_IOCTL_GET_ACCEL start,no accel data\n",__func__);
+ mutex_lock(&sensor->operation_mutex);
+ acc_buf[0] = g_akm_rbuf[6];
+ acc_buf[1] = g_akm_rbuf[7];
+ acc_buf[2] = g_akm_rbuf[8];
+ mutex_unlock(&sensor->operation_mutex);
+ break;
+
+ default:
+ return -ENOTTY;
+ }
+
+ switch (cmd) {
+ case ECS_IOCTL_READ:
+ if (copy_to_user(argp, &rwbuf, rwbuf[0]+1)) {
+ return -EFAULT;
+ }
+ break;
+ case ECS_IOCTL_GETDATA:
+ if (copy_to_user(argp, &compass_data, sizeof(compass_data))) {
+ return -EFAULT;
+ }
+ break;
+ case ECS_IOCTL_GET_OPEN_STATUS:
+ case ECS_IOCTL_GET_CLOSE_STATUS:
+ if (copy_to_user(argp, &status, sizeof(status))) {
+ return -EFAULT;
+ }
+ break;
+ case ECS_IOCTL_GET_DELAY:
+ if (copy_to_user(argp, &delay, sizeof(delay))) {
+ return -EFAULT;
+ }
+ break;
+ case ECS_IOCTL_GET_LAYOUT:
+ if (copy_to_user(argp, &layout, sizeof(layout))) {
+ printk("%s:error:%d\n",__FUNCTION__,__LINE__);
+ return -EFAULT;
+ }
+ break;
+ case ECS_IOCTL_GET_OUTBIT:
+ if (copy_to_user(argp, &outbit, sizeof(outbit))) {
+ printk("%s:error:%d\n",__FUNCTION__,__LINE__);
+ return -EFAULT;
+ }
+ break;
+ case ECS_IOCTL_GET_ACCEL:
+ if (copy_to_user(argp, &acc_buf, sizeof(acc_buf))) {
+ printk("%s:error:%d\n",__FUNCTION__,__LINE__);
+ return -EFAULT;
+ }
+ break;
case ECS_IOCTL_GET_INFO:
if (copy_to_user(argp, &sense_info, sizeof(sense_info))) {
printk("%s:error:%d\n", __FUNCTION__, __LINE__);
return -EFAULT;
}
break;
- default:\r
- break;\r
- }\r
-\r
- return result;\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 = "akm8963_dev",\r
- .fops = &compass_dev_fops,\r
-};\r
-\r
-struct sensor_operate compass_akm8963_ops = {\r
- .name = "akm8963",\r
- .type = SENSOR_TYPE_COMPASS, //it is important\r
- .id_i2c = COMPASS_ID_AK8963,\r
- .read_reg = AK8963_REG_ST1, //read data\r
- .read_len = SENSOR_DATA_SIZE, //data length\r
- .id_reg = AK8963_REG_WIA, //read id\r
- .id_data = AK8963_DEVICE_ID,\r
- .precision = 8, //12 bits\r
- .ctrl_reg = AK8963_REG_CNTL1, //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 = NULL, //private misc support\r
-};\r
-\r
-/****************operate according to sensor chip:end************/\r
-\r
-//function name should not be changed\r
-static struct sensor_operate *compass_get_ops(void)\r
-{\r
- return &compass_akm8963_ops; \r
-}\r
-\r
-\r
-static int __init compass_akm8963_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
- return result;\r
-}\r
-\r
-static void __exit compass_akm8963_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_akm8963_init);\r
-module_exit(compass_akm8963_exit);\r
-\r
-\r
+ default:
+ break;
+ }
+
+ return result;
+}
+
+static struct file_operations compass_dev_fops =
+{
+ .owner = THIS_MODULE,
+ .open = compass_dev_open,
+ .release = compass_dev_release,
+ .unlocked_ioctl = compass_dev_ioctl,
+};
+
+
+static struct miscdevice compass_dev_device =
+{
+ .minor = MISC_DYNAMIC_MINOR,
+ .name = "akm8963_dev",
+ .fops = &compass_dev_fops,
+};
+
+struct sensor_operate compass_akm8963_ops = {
+ .name = "akm8963",
+ .type = SENSOR_TYPE_COMPASS, //it is important
+ .id_i2c = COMPASS_ID_AK8963,
+ .read_reg = AK8963_REG_ST1, //read data
+ .read_len = SENSOR_DATA_SIZE, //data length
+ .id_reg = AK8963_REG_WIA, //read id
+ .id_data = AK8963_DEVICE_ID,
+ .precision = 8, //12 bits
+ .ctrl_reg = AK8963_REG_CNTL1, //enable or disable
+ .int_status_reg = SENSOR_UNKNOW_DATA, //not exist
+ .range = {-0xffff,0xffff},
+ .trig = IRQF_TRIGGER_RISING, //if LEVEL interrupt then IRQF_ONESHOT
+ .active = sensor_active,
+ .init = sensor_init,
+ .report = sensor_report_value,
+ .misc_dev = NULL, //private misc support
+};
+
+/****************operate according to sensor chip:end************/
+
+//function name should not be changed
+static struct sensor_operate *compass_get_ops(void)
+{
+ return &compass_akm8963_ops;
+}
+
+
+static int __init compass_akm8963_init(void)
+{
+ struct sensor_operate *ops = compass_get_ops();
+ int result = 0;
+ int type = ops->type;
+ result = sensor_register_slave(type, NULL, NULL, compass_get_ops);
+
+ return result;
+}
+
+static void __exit compass_akm8963_exit(void)
+{
+ struct sensor_operate *ops = compass_get_ops();
+ int type = ops->type;
+ sensor_unregister_slave(type, NULL, NULL, compass_get_ops);
+}
+
+
+module_init(compass_akm8963_init);
+module_exit(compass_akm8963_exit);
+
+
-/* 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 <linux/of_gpio.h>\r
-#ifdef CONFIG_HAS_EARLYSUSPEND\r
-#include <linux/earlysuspend.h>\r
-#endif\r
-\r
-#include <linux/sensor-dev.h>\r
-\r
-#define SENSOR_DATA_SIZE 8\r
-\r
-\r
-/*! \name AK8975 operation mode\r
- \anchor AK8975_Mode\r
- Defines an operation mode of the AK8975.*/\r
-/*! @{*/\r
-#define AK8975_MODE_SNG_MEASURE 0x01\r
-#define AK8975_MODE_SELF_TEST 0x08\r
-#define AK8975_MODE_FUSE_ACCESS 0x0F\r
-#define AK8975_MODE_POWERDOWN 0x00\r
-/*! @}*/\r
-\r
-#define SENSOR_DATA_SIZE 8 /* Rx buffer size, i.e from ST1 to ST2 */\r
-#define RWBUF_SIZE 16 /* Read/Write buffer size.*/\r
-\r
-\r
-/*! \name AK8975 register address\r
-\anchor AK8975_REG\r
-Defines a register address of the AK8975.*/\r
-/*! @{*/\r
-#define AK8975_REG_WIA 0x00\r
-#define AK8975_REG_INFO 0x01\r
-#define AK8975_REG_ST1 0x02\r
-#define AK8975_REG_HXL 0x03\r
-#define AK8975_REG_HXH 0x04\r
-#define AK8975_REG_HYL 0x05\r
-#define AK8975_REG_HYH 0x06\r
-#define AK8975_REG_HZL 0x07\r
-#define AK8975_REG_HZH 0x08\r
-#define AK8975_REG_ST2 0x09\r
-#define AK8975_REG_CNTL 0x0A\r
-#define AK8975_REG_RSV 0x0B\r
-#define AK8975_REG_ASTC 0x0C\r
-#define AK8975_REG_TS1 0x0D\r
-#define AK8975_REG_TS2 0x0E\r
-#define AK8975_REG_I2CDIS 0x0F\r
-/*! @}*/\r
-\r
-/*! \name AK8975 fuse-rom address\r
-\anchor AK8975_FUSE\r
-Defines a read-only address of the fuse ROM of the AK8975.*/\r
-/*! @{*/\r
-#define AK8975_FUSE_ASAX 0x10\r
-#define AK8975_FUSE_ASAY 0x11\r
-#define AK8975_FUSE_ASAZ 0x12\r
-/*! @}*/\r
-\r
-#define AK8975_INFO_DATA (0x01<<3)\r
-\r
-\r
-#define COMPASS_IOCTL_MAGIC 'c'\r
-\r
-/* IOCTLs for AKM library */\r
-#define ECS_IOCTL_WRITE _IOW(COMPASS_IOCTL_MAGIC, 0x01, char*)\r
-#define ECS_IOCTL_READ _IOWR(COMPASS_IOCTL_MAGIC, 0x02, char*)\r
-#define ECS_IOCTL_RESET _IO(COMPASS_IOCTL_MAGIC, 0x03) /* NOT used in AK8975 */\r
-#define ECS_IOCTL_SET_MODE _IOW(COMPASS_IOCTL_MAGIC, 0x04, short)\r
-#define ECS_IOCTL_GETDATA _IOR(COMPASS_IOCTL_MAGIC, 0x05, char[SENSOR_DATA_SIZE])\r
-#define ECS_IOCTL_SET_YPR _IOW(COMPASS_IOCTL_MAGIC, 0x06, short[12])\r
-#define ECS_IOCTL_GET_OPEN_STATUS _IOR(COMPASS_IOCTL_MAGIC, 0x07, int)\r
-#define ECS_IOCTL_GET_CLOSE_STATUS _IOR(COMPASS_IOCTL_MAGIC, 0x08, int)\r
-#define ECS_IOCTL_GET_LAYOUT _IOR(COMPASS_IOCTL_MAGIC, 0x09, char)\r
-#define ECS_IOCTL_GET_ACCEL _IOR(COMPASS_IOCTL_MAGIC, 0x0A, short[3])\r
-#define ECS_IOCTL_GET_OUTBIT _IOR(COMPASS_IOCTL_MAGIC, 0x0B, char)\r
-#define ECS_IOCTL_GET_DELAY _IOR(COMPASS_IOCTL_MAGIC, 0x30, short)\r
-#define ECS_IOCTL_GET_PROJECT_NAME _IOR(COMPASS_IOCTL_MAGIC, 0x0D, char[64])\r
-#define ECS_IOCTL_GET_MATRIX _IOR(COMPASS_IOCTL_MAGIC, 0x0E, short [4][3][3])\r
-#define ECS_IOCTL_GET_PLATFORM_DATA _IOR(COMPASS_IOCTL_MAGIC, 0x0E, struct akm_platform_data)\r
-\r
-\r
-#define AK8975_DEVICE_ID 0x48\r
-static struct i2c_client *this_client;\r
-static struct miscdevice compass_dev_device;\r
-\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
- \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
- sensor->ops->ctrl_data = AK8975_MODE_SNG_MEASURE; \r
- }\r
- else\r
- {\r
- sensor->ops->ctrl_data = AK8975_MODE_POWERDOWN;\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
- int info = 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
- info = sensor_read_reg(client, AK8975_REG_INFO);\r
- if((info & (0x0f<<3)) != AK8975_INFO_DATA)\r
- \r
- {\r
- printk("%s:info=0x%x,it is not %s\n",__func__, info, sensor->ops->name);\r
- return -1;\r
- }\r
-\r
- result = misc_register(&compass_dev_device);\r
- if (result < 0) {\r
- printk("%s:fail to register misc device %s\n", __func__, compass_dev_device.name);\r
- result = -1;\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
- char value = 0;\r
- int i;\r
-\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
+/* drivers/input/sensors/access/akm8975.c
+ *
+ * Copyright (C) 2012-2015 ROCKCHIP.
+ * Author: luowei <lw@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>
+
+#define SENSOR_DATA_SIZE 8
+
+
+/*! \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_POWERDOWN 0x00
+/*! @}*/
+
+#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
+Defines a register address of the AK8975.*/
+/*! @{*/
+#define AK8975_REG_WIA 0x00
+#define AK8975_REG_INFO 0x01
+#define AK8975_REG_ST1 0x02
+#define AK8975_REG_HXL 0x03
+#define AK8975_REG_HXH 0x04
+#define AK8975_REG_HYL 0x05
+#define AK8975_REG_HYH 0x06
+#define AK8975_REG_HZL 0x07
+#define AK8975_REG_HZH 0x08
+#define AK8975_REG_ST2 0x09
+#define AK8975_REG_CNTL 0x0A
+#define AK8975_REG_RSV 0x0B
+#define AK8975_REG_ASTC 0x0C
+#define AK8975_REG_TS1 0x0D
+#define AK8975_REG_TS2 0x0E
+#define AK8975_REG_I2CDIS 0x0F
+/*! @}*/
+
+/*! \name AK8975 fuse-rom address
+\anchor AK8975_FUSE
+Defines a read-only address of the fuse ROM of the AK8975.*/
+/*! @{*/
+#define AK8975_FUSE_ASAX 0x10
+#define AK8975_FUSE_ASAY 0x11
+#define AK8975_FUSE_ASAZ 0x12
+/*! @}*/
+
+#define AK8975_INFO_DATA (0x01<<3)
+
+
+#define COMPASS_IOCTL_MAGIC 'c'
+
+/* IOCTLs for AKM library */
+#define ECS_IOCTL_WRITE _IOW(COMPASS_IOCTL_MAGIC, 0x01, char*)
+#define ECS_IOCTL_READ _IOWR(COMPASS_IOCTL_MAGIC, 0x02, char*)
+#define ECS_IOCTL_RESET _IO(COMPASS_IOCTL_MAGIC, 0x03) /* NOT used in AK8975 */
+#define ECS_IOCTL_SET_MODE _IOW(COMPASS_IOCTL_MAGIC, 0x04, short)
+#define ECS_IOCTL_GETDATA _IOR(COMPASS_IOCTL_MAGIC, 0x05, char[SENSOR_DATA_SIZE])
+#define ECS_IOCTL_SET_YPR _IOW(COMPASS_IOCTL_MAGIC, 0x06, short[12])
+#define ECS_IOCTL_GET_OPEN_STATUS _IOR(COMPASS_IOCTL_MAGIC, 0x07, int)
+#define ECS_IOCTL_GET_CLOSE_STATUS _IOR(COMPASS_IOCTL_MAGIC, 0x08, int)
+#define ECS_IOCTL_GET_LAYOUT _IOR(COMPASS_IOCTL_MAGIC, 0x09, char)
+#define ECS_IOCTL_GET_ACCEL _IOR(COMPASS_IOCTL_MAGIC, 0x0A, short[3])
+#define ECS_IOCTL_GET_OUTBIT _IOR(COMPASS_IOCTL_MAGIC, 0x0B, char)
+#define ECS_IOCTL_GET_DELAY _IOR(COMPASS_IOCTL_MAGIC, 0x30, short)
+#define ECS_IOCTL_GET_PROJECT_NAME _IOR(COMPASS_IOCTL_MAGIC, 0x0D, char[64])
+#define ECS_IOCTL_GET_MATRIX _IOR(COMPASS_IOCTL_MAGIC, 0x0E, short [4][3][3])
+#define ECS_IOCTL_GET_PLATFORM_DATA _IOR(COMPASS_IOCTL_MAGIC, 0x0E, struct akm_platform_data)
+
+
+#define AK8975_DEVICE_ID 0x48
+static struct i2c_client *this_client;
+static struct miscdevice compass_dev_device;
+
+
+
+
+/****************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;
+
+ //sensor->ops->ctrl_data = sensor_read_reg(client, sensor->ops->ctrl_reg);
+
+ //register setting according to chip datasheet
+ if(enable)
+ {
+ sensor->ops->ctrl_data = AK8975_MODE_SNG_MEASURE;
+ }
+ else
+ {
+ sensor->ops->ctrl_data = AK8975_MODE_POWERDOWN;
+ }
+
+ 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;
+ int info = 0;
+
+ this_client = client;
+
+ result = sensor->ops->active(client,0,0);
+ if(result)
+ {
+ printk("%s:line=%d,error\n",__func__,__LINE__);
+ return result;
+ }
+
+ sensor->status_cur = SENSOR_OFF;
+
+ info = sensor_read_reg(client, AK8975_REG_INFO);
+ if((info & (0x0f<<3)) != AK8975_INFO_DATA)
+
+ {
+ printk("%s:info=0x%x,it is not %s\n",__func__, info, sensor->ops->name);
+ return -1;
+ }
+
+ result = misc_register(&compass_dev_device);
+ if (result < 0) {
+ printk("%s:fail to register misc device %s\n", __func__, compass_dev_device.name);
+ result = -1;
+ }
+
+ DBG("%s:status_cur=%d\n",__func__, sensor->status_cur);
+ return result;
+}
+
+static int sensor_report_value(struct i2c_client *client)
+{
+ struct sensor_private_data *sensor =
+ (struct sensor_private_data *) i2c_get_clientdata(client);
+ char buffer[8] = {0};
+ unsigned char *stat;
+ unsigned char *stat2;
+ int ret = 0;
+ char value = 0;
+ int i;
+
+ if(sensor->ops->read_len < 8) //sensor->ops->read_len = 8
+ {
+ 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);
+
+ stat = &buffer[0];
+ stat2 = &buffer[7];
+
+ /*
* 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
+ */
+ if ((*stat & 0x01) != 0x01) {
+ DBG(KERN_ERR "%s:ST is not set\n",__func__);
+ return -1;
+ }
/*
* ST2 : data error -
* 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
+ if (*stat2 & 0x04)
+ {
+ DBG(KERN_ERR "%s:compass data error\n",__func__);
+ return -2;
+ }
+
/*
* ST2 : overflow -
* the sum of the absolute values of all axis |X|+|Y|+|Z| < 2400uT.
* 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
- DBG("%s:",__func__);\r
- for(i=0; i<sensor->ops->read_len; i++)\r
- DBG("0x%x,",buffer[i]);\r
- DBG("\n");\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
- \r
- //trigger next measurement \r
- ret = sensor_write_reg(client, sensor->ops->ctrl_reg, sensor->ops->ctrl_data);\r
- if(ret)\r
- {\r
- printk(KERN_ERR "%s:fail to set ctrl_data:0x%x\n",__func__,sensor->ops->ctrl_data);\r
- return ret;\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(&sensor->flags.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(&sensor->flags.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(&sensor->flags.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
-static int compass_dev_open(struct inode *inode, struct file *file)\r
-{\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
- 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
- struct sensor_private_data* sensor = (struct sensor_private_data *)i2c_get_clientdata(this_client); \r
- wait_event_interruptible(sensor->flags.open_wq, (atomic_read(&sensor->flags.open_flag) != 0));\r
- return atomic_read(&sensor->flags.open_flag);\r
-}\r
-\r
-static int compass_akm_get_closestatus(void)\r
-{\r
- struct sensor_private_data* sensor = (struct sensor_private_data *)i2c_get_clientdata(this_client); \r
- wait_event_interruptible(sensor->flags.open_wq, (atomic_read(&sensor->flags.open_flag) <= 0));\r
- return atomic_read(&sensor->flags.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 akm_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
- if(sensor->ops->ctrl_data != mode)\r
- {\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
- \r
- sensor->ops->ctrl_data = mode;\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
+ if (*stat2 & 0x08)
+ {
+ DBG(KERN_ERR "%s:compass data overflow\n",__func__);
+ return -3;
+ }
+
+ /* »¥³âµØ»º´æÊý¾Ý. */
+ mutex_lock(&sensor->data_mutex);
+ memcpy(sensor->sensor_data, buffer, sensor->ops->read_len);
+ mutex_unlock(&sensor->data_mutex);
+ DBG("%s:",__func__);
+ for(i=0; i<sensor->ops->read_len; i++)
+ DBG("0x%x,",buffer[i]);
+ DBG("\n");
+
+ 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);
+ }
+
+
+ //trigger next measurement
+ ret = sensor_write_reg(client, sensor->ops->ctrl_reg, sensor->ops->ctrl_data);
+ if(ret)
+ {
+ printk(KERN_ERR "%s:fail to set ctrl_data:0x%x\n",__func__,sensor->ops->ctrl_data);
+ return ret;
+ }
+
+ return ret;
+}
+
+static void compass_set_YPR(short *rbuf)
+{
+ struct sensor_private_data *sensor =
+ (struct sensor_private_data *) i2c_get_clientdata(this_client);
+
+ /* Report magnetic sensor information */
+ if (atomic_read(&sensor->flags.m_flag)) {
+ input_report_abs(sensor->input_dev, ABS_RX, rbuf[0]);
+ input_report_abs(sensor->input_dev, ABS_RY, rbuf[1]);
+ input_report_abs(sensor->input_dev, ABS_RZ, rbuf[2]);
+ input_report_abs(sensor->input_dev, ABS_RUDDER, rbuf[4]);
+ DBG("%s:m_flag:x=%d,y=%d,z=%d,RUDDER=%d\n",__func__,rbuf[0], rbuf[1], rbuf[2], rbuf[4]);
+ }
+
+ /* Report acceleration sensor information */
+ if (atomic_read(&sensor->flags.a_flag)) {
+ input_report_abs(sensor->input_dev, ABS_X, rbuf[6]);
+ input_report_abs(sensor->input_dev, ABS_Y, rbuf[7]);
+ input_report_abs(sensor->input_dev, ABS_Z, rbuf[8]);
+ input_report_abs(sensor->input_dev, ABS_WHEEL, rbuf[5]);
+
+ DBG("%s:a_flag:x=%d,y=%d,z=%d,WHEEL=%d\n",__func__,rbuf[6], rbuf[7], rbuf[8], rbuf[5]);
+ }
+
+ /* Report magnetic vector information */
+ if (atomic_read(&sensor->flags.mv_flag)) {
+ input_report_abs(sensor->input_dev, ABS_HAT0X, rbuf[9]);
+ input_report_abs(sensor->input_dev, ABS_HAT0Y, rbuf[10]);
+ input_report_abs(sensor->input_dev, ABS_BRAKE, rbuf[11]);
+
+ DBG("%s:mv_flag:x=%d,y=%d,BRAKE=%d\n",__func__,rbuf[9], rbuf[10], rbuf[11]);
+ }
+
+ input_sync(sensor->input_dev);
+}
+
+
+static int compass_dev_open(struct inode *inode, struct file *file)
+{
+ int result = 0;
+ DBG("%s\n",__func__);
+
+ return result;
+}
+
+
+static int compass_dev_release(struct inode *inode, struct file *file)
+{
+ int result = 0;
+ DBG("%s\n",__func__);
+
+ return result;
+}
+
+static int compass_akm_set_mode(struct i2c_client *client, char mode)
+{
+ struct sensor_private_data* sensor = (struct sensor_private_data *)i2c_get_clientdata(this_client);
+ int result = 0;
+
+ switch(mode)
+ {
+ case AK8975_MODE_SNG_MEASURE:
+ case AK8975_MODE_SELF_TEST:
+ case AK8975_MODE_FUSE_ACCESS:
+ if(sensor->status_cur == SENSOR_OFF)
+ {
+ if(sensor->pdata->irq_enable)
+ {
+ //DBG("%s:enable irq=%d\n",__func__,client->irq);
+ //enable_irq(client->irq);
+ }
+ else
+ {
+ schedule_delayed_work(&sensor->delaywork, msecs_to_jiffies(sensor->pdata->poll_delay_ms));
+ }
+
+ sensor->status_cur = SENSOR_ON;
+ }
+
+ break;
+
+ case AK8975_MODE_POWERDOWN:
+ if(sensor->status_cur == SENSOR_ON)
+ {
+ if(sensor->pdata->irq_enable)
+ {
+ //DBG("%s:disable irq=%d\n",__func__,client->irq);
+ //disable_irq_nosync(client->irq);//disable irq
+ }
+ else
+ cancel_delayed_work_sync(&sensor->delaywork);
+
+ sensor->status_cur = SENSOR_OFF;
+ }
+ break;
+
+ }
+
+ switch(mode)
+ {
+ case AK8975_MODE_SNG_MEASURE:
+ result = sensor_write_reg(client, sensor->ops->ctrl_reg, AK8975_MODE_SNG_MEASURE);
+ if(result)
+ printk("%s:i2c error,mode=%d\n",__func__,mode);
+ break;
+ case AK8975_MODE_SELF_TEST:
+ result = sensor_write_reg(client, sensor->ops->ctrl_reg, AK8975_MODE_SELF_TEST);
+ if(result)
+ printk("%s:i2c error,mode=%d\n",__func__,mode);
+ break;
+ case AK8975_MODE_FUSE_ACCESS:
+ result = sensor_write_reg(client, sensor->ops->ctrl_reg, AK8975_MODE_FUSE_ACCESS);
+ if(result)
+ printk("%s:i2c error,mode=%d\n",__func__,mode);
+ break;
+ case AK8975_MODE_POWERDOWN:
+ /* Set powerdown mode */
+ result = sensor_write_reg(client, sensor->ops->ctrl_reg, AK8975_MODE_POWERDOWN);
+ if(result)
+ printk("%s:i2c error,mode=%d\n",__func__,mode);
+ udelay(100);
+ break;
+ default:
+ printk("%s: Unknown mode(%d)", __func__, mode);
+ result = -EINVAL;
+ break;
+ }
+ DBG("%s:mode=%d\n",__func__,mode);
+ return result;
+
+}
+
+
+static int compass_akm_get_openstatus(void)
+{
+ struct sensor_private_data* sensor = (struct sensor_private_data *)i2c_get_clientdata(this_client);
+ wait_event_interruptible(sensor->flags.open_wq, (atomic_read(&sensor->flags.open_flag) != 0));
+ return atomic_read(&sensor->flags.open_flag);
+}
+
+static int compass_akm_get_closestatus(void)
+{
+ struct sensor_private_data* sensor = (struct sensor_private_data *)i2c_get_clientdata(this_client);
+ wait_event_interruptible(sensor->flags.open_wq, (atomic_read(&sensor->flags.open_flag) <= 0));
+ return atomic_read(&sensor->flags.open_flag);
+}
+
+
+/* ioctl - I/O control */
+static long compass_dev_ioctl(struct file *file,
+ unsigned int cmd, unsigned long arg)
+{
+ struct sensor_private_data* sensor = (struct sensor_private_data *)i2c_get_clientdata(this_client);
+ struct i2c_client *client = this_client;
+ void __user *argp = (void __user *)arg;
+ int result = 0;
+ struct akm_platform_data compass;
+
+ /* NOTE: In this function the size of "char" should be 1-byte. */
+ char compass_data[SENSOR_DATA_SIZE];/* for GETDATA */
+ char rwbuf[RWBUF_SIZE]; /* for READ/WRITE */
+ char mode; /* for SET_MODE*/
+ short value[12]; /* for SET_YPR */
+ short delay; /* for GET_DELAY */
+ int status; /* for OPEN/CLOSE_STATUS */
+ int ret = -1; /* Return value. */
+
+ switch (cmd) {
+ case ECS_IOCTL_WRITE:
+ case ECS_IOCTL_READ:
+ if (argp == NULL) {
+ return -EINVAL;
+ }
+ if (copy_from_user(&rwbuf, argp, sizeof(rwbuf))) {
+ return -EFAULT;
+ }
+ break;
+ case ECS_IOCTL_SET_MODE:
+ if (argp == NULL) {
+ return -EINVAL;
+ }
+ if (copy_from_user(&mode, argp, sizeof(mode))) {
+ return -EFAULT;
+ }
+ break;
+ case ECS_IOCTL_SET_YPR:
+ if (argp == NULL) {
+ return -EINVAL;
+ }
+ if (copy_from_user(&value, argp, sizeof(value))) {
+ return -EFAULT;
+ }
+ break;
+ default:
+ break;
+ }
+
+ switch (cmd) {
+ case ECS_IOCTL_WRITE:
+ DBG("%s:ECS_IOCTL_WRITE start\n",__func__);
+ mutex_lock(&sensor->operation_mutex);
+ if ((rwbuf[0] < 2) || (rwbuf[0] > (RWBUF_SIZE-1))) {
+ mutex_unlock(&sensor->operation_mutex);
+ return -EINVAL;
+ }
+ ret = sensor_tx_data(client, &rwbuf[1], rwbuf[0]);
+ if (ret < 0) {
+ mutex_unlock(&sensor->operation_mutex);
+ printk("%s:fait to tx data\n",__func__);
+ return ret;
+ }
+ mutex_unlock(&sensor->operation_mutex);
+ break;
+ case ECS_IOCTL_READ:
+ DBG("%s:ECS_IOCTL_READ start\n",__func__);
+ mutex_lock(&sensor->operation_mutex);
+ if ((rwbuf[0] < 1) || (rwbuf[0] > (RWBUF_SIZE-1))) {
+ mutex_unlock(&sensor->operation_mutex);
+ printk("%s:data is error\n",__func__);
+ return -EINVAL;
+ }
+ ret = sensor_rx_data(client, &rwbuf[1], rwbuf[0]);
+ if (ret < 0) {
+ mutex_unlock(&sensor->operation_mutex);
+ printk("%s:fait to rx data\n",__func__);
+ return ret;
+ }
+ mutex_unlock(&sensor->operation_mutex);
+ break;
+ case ECS_IOCTL_SET_MODE:
+ DBG("%s:ECS_IOCTL_SET_MODE start\n",__func__);
+ mutex_lock(&sensor->operation_mutex);
+ if(sensor->ops->ctrl_data != mode)
+ {
+ ret = compass_akm_set_mode(client, mode);
+ if (ret < 0) {
+ printk("%s:fait to set mode\n",__func__);
+ mutex_unlock(&sensor->operation_mutex);
+ return ret;
+ }
+
+ sensor->ops->ctrl_data = mode;
+ }
+ mutex_unlock(&sensor->operation_mutex);
+ break;
+ case ECS_IOCTL_GETDATA:
+ DBG("%s:ECS_IOCTL_GETDATA start\n",__func__);
+ mutex_lock(&sensor->data_mutex);
+ memcpy(compass_data, sensor->sensor_data, SENSOR_DATA_SIZE); //get data from buffer
+ mutex_unlock(&sensor->data_mutex);
+ break;
+ case ECS_IOCTL_SET_YPR:
+ DBG("%s:ECS_IOCTL_SET_YPR start\n",__func__);
+ mutex_lock(&sensor->data_mutex);
+ compass_set_YPR(value);
+ mutex_unlock(&sensor->data_mutex);
+ break;
+ case ECS_IOCTL_GET_OPEN_STATUS:
+ status = compass_akm_get_openstatus();
+ DBG("%s:openstatus=%d\n",__func__,status);
+ break;
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 = sensor->flags.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
-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 compass_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 = NULL, //private misc support\r
-};\r
-\r
-/****************operate according to sensor chip:end************/\r
-\r
-//function name should not be changed\r
-static struct sensor_operate *compass_get_ops(void)\r
-{\r
- return &compass_akm8975_ops; \r
-}\r
-\r
-\r
-static int __init compass_akm8975_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
- return result;\r
-}\r
-\r
-static void __exit compass_akm8975_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_akm8975_init);\r
-module_exit(compass_akm8975_exit);\r
-\r
-\r
+ status = compass_akm_get_closestatus();
+ DBG("%s:closestatus=%d\n",__func__,status);
+ break;
+ case ECS_IOCTL_GET_DELAY:
+ delay = sensor->flags.delay;
+ break;
+ case ECS_IOCTL_GET_PLATFORM_DATA:
+ DBG("%s:ECS_IOCTL_GET_PLATFORM_DATA start\n",__func__);
+ //memcpy(compass.m_layout, sensor->pdata->m_layout, sizeof(sensor->pdata->m_layout));
+ //memcpy(compass.project_name, sensor->pdata->project_name, sizeof(sensor->pdata->project_name));
+ ret = copy_to_user(argp, &compass, sizeof(compass));
+ if(ret < 0)
+ {
+ printk("%s:error,ret=%d\n",__FUNCTION__, ret);
+ return ret;
+ }
+ break;
+
+ default:
+ return -ENOTTY;
+ }
+
+ switch (cmd) {
+ case ECS_IOCTL_READ:
+ if (copy_to_user(argp, &rwbuf, rwbuf[0]+1)) {
+ return -EFAULT;
+ }
+ break;
+ case ECS_IOCTL_GETDATA:
+ if (copy_to_user(argp, &compass_data, sizeof(compass_data))) {
+ return -EFAULT;
+ }
+ break;
+ case ECS_IOCTL_GET_OPEN_STATUS:
+ case ECS_IOCTL_GET_CLOSE_STATUS:
+ if (copy_to_user(argp, &status, sizeof(status))) {
+ return -EFAULT;
+ }
+ break;
+ case ECS_IOCTL_GET_DELAY:
+ if (copy_to_user(argp, &delay, sizeof(delay))) {
+ return -EFAULT;
+ }
+ break;
+ default:
+ break;
+ }
+
+ return result;
+}
+
+static struct file_operations compass_dev_fops =
+{
+ .owner = THIS_MODULE,
+ .open = compass_dev_open,
+ .release = compass_dev_release,
+ .unlocked_ioctl = compass_dev_ioctl,
+};
+
+
+static struct miscdevice compass_dev_device =
+{
+ .minor = MISC_DYNAMIC_MINOR,
+ .name = "akm8975_dev",
+ .fops = &compass_dev_fops,
+};
+
+struct sensor_operate compass_akm8975_ops = {
+ .name = "akm8975",
+ .type = SENSOR_TYPE_COMPASS, //it is important
+ .id_i2c = COMPASS_ID_AK8975,
+ .read_reg = AK8975_REG_ST1, //read data
+ .read_len = SENSOR_DATA_SIZE, //data length
+ .id_reg = AK8975_REG_WIA, //read id
+ .id_data = AK8975_DEVICE_ID,
+ .precision = 8, //12 bits
+ .ctrl_reg = AK8975_REG_CNTL, //enable or disable
+ .int_status_reg = SENSOR_UNKNOW_DATA, //not exist
+ .range = {-0xffff,0xffff},
+ .trig = IRQF_TRIGGER_RISING, //if LEVEL interrupt then IRQF_ONESHOT
+ .active = sensor_active,
+ .init = sensor_init,
+ .report = sensor_report_value,
+ .misc_dev = NULL, //private misc support
+};
+
+/****************operate according to sensor chip:end************/
+
+//function name should not be changed
+static struct sensor_operate *compass_get_ops(void)
+{
+ return &compass_akm8975_ops;
+}
+
+
+static int __init compass_akm8975_init(void)
+{
+ struct sensor_operate *ops = compass_get_ops();
+ int result = 0;
+ int type = ops->type;
+ result = sensor_register_slave(type, NULL, NULL, compass_get_ops);
+
+ return result;
+}
+
+static void __exit compass_akm8975_exit(void)
+{
+ struct sensor_operate *ops = compass_get_ops();
+ int type = ops->type;
+ sensor_unregister_slave(type, NULL, NULL, compass_get_ops);
+}
+
+
+module_init(compass_akm8975_init);
+module_exit(compass_akm8975_exit);
+
+
-/* drivers/input/sensors/gyro/Ewtsa.c\r
- *\r
- * Copyright (C) 2012-2015 ROCKCHIP.\r
- * Author: zhangaihui <zah@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
-/** This define controls compilation of the master device interface */\r
-/*#define EWTSA_MASTER_DEVICE*/\r
-/* configurable */\r
-#define GYRO_MOUNT_SWAP_XY 0 /* swap X, Y */\r
-#define GYRO_MOUNT_REVERSE_X 0 /* reverse X */\r
-#define GYRO_MOUNT_REVERSE_Y 0 /* reverse Y */\r
-#define GYRO_MOUNT_REVERSE_Z 0 /* reverse Z */\r
-\r
-/* macro defines */\r
-/*#define CHIP_ID 0x68*/\r
-#define DEVICE_NAME "ewtsa"\r
-#define EWTSA_ON 1\r
-#define EWTSA_OFF 0\r
-#define SLEEP_PIN 14\r
-#define DRDY_PIN 12\r
-#define DIAG_PIN 11\r
-#define MAX_VALUE 32768\r
-\r
-/* ewtsa_delay parameter */\r
-#define DELAY_THRES_MIN 1\r
-#define DELAY_THRES_1 4\r
-#define DELAY_THRES_2 9 /* msec x 90% */\r
-#define DELAY_THRES_3 18\r
-#define DELAY_THRES_4 45\r
-#define DELAY_THRES_5 90\r
-#define DELAY_THRES_6 128\r
-#define DELAY_THRES_MAX 255\r
-#define DELAY_DLPF_2 2\r
-#define DELAY_DLPF_3 3\r
-#define DELAY_DLPF_4 4\r
-#define DELAY_DLPF_5 5\r
-#define DELAY_DLPF_6 6\r
-#define DELAY_INTMIN_THRES 9\r
-\r
-#define DATA_RATE_1 0x01\r
-\r
-/* ewtsa_sleep parameter */\r
-#define SLEEP_OFF 0\r
-#define SLEEP_ON 1\r
-\r
-/* event mode */\r
-#define EWTSA_POLLING_MODE 0\r
-#define EWTSA_INTERUPT_MODE 1\r
-\r
-/* ewtsa register address */\r
-#define REG_SMPL 0x15\r
-#define REG_FS_DLPF 0x16\r
-#define REG_INT_CFG 0x17\r
-#define REG_INT_STATUS 0x1A\r
-#define REG_SELF_O_C 0x29\r
-#define REG_PWR_MGM 0x3E\r
-#define REG_MBURST_ALL 0xFF\r
-#define GYRO_DATA_REG 0x1D\r
-\r
-/* ewtsa register param */\r
-#define SELF_O_C_ENABLE 0x00\r
-#define SELF_O_C_DISABLE 0x01\r
-#define SLEEP_CTRL_ACTIVATE 0x40\r
-#define SLEEP_CTRL_SLEEP 0x00\r
-#define INT_CFG_INT_ENABLE 0x01\r
-#define INT_CFG_INT_DISABLE 0x00\r
-\r
-/* ewtsa interrupt control */\r
-#define EWSTA_INT_CLEAR 0x00\r
-#define EWSTA_INT_SKIP 0x01\r
-\r
-/* wait time(ms)*/\r
-#define EWTSA_BOOST_TIME_0 500\r
-\r
-/* sleep setting range */\r
-#define EWTSA_SLP_MIN 0\r
-#define EWTSA_SLP_MAX 1\r
-\r
-/* delay setting range */\r
-#define EWTSA_DLY_MIN 1\r
-#define EWTSA_DLY_MAX 255\r
-\r
-/* range setting range */\r
-#define EWTSA_RNG_MIN 0\r
-#define EWTSA_RNG_MAX 3\r
-\r
-/* soc setting range */\r
-#define EWTSA_SOC_MIN 0\r
-#define EWTSA_SOC_MAX 1\r
-\r
-/* event setting range */\r
-#define EWTSA_EVE_MIN 0\r
-#define EWTSA_EVE_MAX 1\r
-\r
-/* init param */\r
-#define SLEEP_INIT_VAL (SLEEP_ON)\r
-#define DELAY_INIT_VAL 10\r
-#define RANGE_INIT_VAL 2 /*range 1000*/\r
-#define DLPF_INIT_VAL (DELAY_DLPF_2)\r
-#define CALIB_FUNC_INIT_VAL (EWTSA_ON)\r
-\r
-/*config store counter num*/\r
-#define CONFIG_COUNTER_MIN (6+9)\r
-#define CONFIG_COUNTER_MAX (32+9)\r
-\r
-/*command name */\r
-#define COMMAND_NAME_SOC 0\r
-#define COMMAND_NAME_DLY 1\r
-#define COMMAND_NAME_RNG 2\r
-#define COMMAND_NAME_EVE 3\r
-#define COMMAND_NAME_SLP 4\r
-#define COMMAND_NAME_NUM 5\r
-\r
-#define EWTSA_delay DELAY_INIT_VAL\r
-#define EWTSA_range RANGE_INIT_VAL\r
-#define EWTSA_calib EWTSA_ON\r
-\r
-/****************operate according to sensor chip:start************/\r
-static int i2c_read_byte(struct i2c_client *thisClient, unsigned char regAddr, char *pReadData)\r
+/* drivers/input/sensors/gyro/Ewtsa.c
+ *
+ * Copyright (C) 2012-2015 ROCKCHIP.
+ * Author: zhangaihui <zah@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>
+
+/** This define controls compilation of the master device interface */
+/*#define EWTSA_MASTER_DEVICE*/
+/* configurable */
+#define GYRO_MOUNT_SWAP_XY 0 /* swap X, Y */
+#define GYRO_MOUNT_REVERSE_X 0 /* reverse X */
+#define GYRO_MOUNT_REVERSE_Y 0 /* reverse Y */
+#define GYRO_MOUNT_REVERSE_Z 0 /* reverse Z */
+
+/* macro defines */
+/*#define CHIP_ID 0x68*/
+#define DEVICE_NAME "ewtsa"
+#define EWTSA_ON 1
+#define EWTSA_OFF 0
+#define SLEEP_PIN 14
+#define DRDY_PIN 12
+#define DIAG_PIN 11
+#define MAX_VALUE 32768
+
+/* ewtsa_delay parameter */
+#define DELAY_THRES_MIN 1
+#define DELAY_THRES_1 4
+#define DELAY_THRES_2 9 /* msec x 90% */
+#define DELAY_THRES_3 18
+#define DELAY_THRES_4 45
+#define DELAY_THRES_5 90
+#define DELAY_THRES_6 128
+#define DELAY_THRES_MAX 255
+#define DELAY_DLPF_2 2
+#define DELAY_DLPF_3 3
+#define DELAY_DLPF_4 4
+#define DELAY_DLPF_5 5
+#define DELAY_DLPF_6 6
+#define DELAY_INTMIN_THRES 9
+
+#define DATA_RATE_1 0x01
+
+/* ewtsa_sleep parameter */
+#define SLEEP_OFF 0
+#define SLEEP_ON 1
+
+/* event mode */
+#define EWTSA_POLLING_MODE 0
+#define EWTSA_INTERUPT_MODE 1
+
+/* ewtsa register address */
+#define REG_SMPL 0x15
+#define REG_FS_DLPF 0x16
+#define REG_INT_CFG 0x17
+#define REG_INT_STATUS 0x1A
+#define REG_SELF_O_C 0x29
+#define REG_PWR_MGM 0x3E
+#define REG_MBURST_ALL 0xFF
+#define GYRO_DATA_REG 0x1D
+
+/* ewtsa register param */
+#define SELF_O_C_ENABLE 0x00
+#define SELF_O_C_DISABLE 0x01
+#define SLEEP_CTRL_ACTIVATE 0x40
+#define SLEEP_CTRL_SLEEP 0x00
+#define INT_CFG_INT_ENABLE 0x01
+#define INT_CFG_INT_DISABLE 0x00
+
+/* ewtsa interrupt control */
+#define EWSTA_INT_CLEAR 0x00
+#define EWSTA_INT_SKIP 0x01
+
+/* wait time(ms)*/
+#define EWTSA_BOOST_TIME_0 500
+
+/* sleep setting range */
+#define EWTSA_SLP_MIN 0
+#define EWTSA_SLP_MAX 1
+
+/* delay setting range */
+#define EWTSA_DLY_MIN 1
+#define EWTSA_DLY_MAX 255
+
+/* range setting range */
+#define EWTSA_RNG_MIN 0
+#define EWTSA_RNG_MAX 3
+
+/* soc setting range */
+#define EWTSA_SOC_MIN 0
+#define EWTSA_SOC_MAX 1
+
+/* event setting range */
+#define EWTSA_EVE_MIN 0
+#define EWTSA_EVE_MAX 1
+
+/* init param */
+#define SLEEP_INIT_VAL (SLEEP_ON)
+#define DELAY_INIT_VAL 10
+#define RANGE_INIT_VAL 2 /*range 1000*/
+#define DLPF_INIT_VAL (DELAY_DLPF_2)
+#define CALIB_FUNC_INIT_VAL (EWTSA_ON)
+
+/*config store counter num*/
+#define CONFIG_COUNTER_MIN (6+9)
+#define CONFIG_COUNTER_MAX (32+9)
+
+/*command name */
+#define COMMAND_NAME_SOC 0
+#define COMMAND_NAME_DLY 1
+#define COMMAND_NAME_RNG 2
+#define COMMAND_NAME_EVE 3
+#define COMMAND_NAME_SLP 4
+#define COMMAND_NAME_NUM 5
+
+#define EWTSA_delay DELAY_INIT_VAL
+#define EWTSA_range RANGE_INIT_VAL
+#define EWTSA_calib EWTSA_ON
+
+/****************operate according to sensor chip:start************/
+static int i2c_read_byte(struct i2c_client *thisClient, unsigned char regAddr, char *pReadData)
{
int ret = 0;
-
+
ret = i2c_master_send( thisClient, (char*)®Addr, 1);
if(ret < 0)
{
- printk("EWTSA send cAddress=0x%x error!\n", regAddr);\r
+ printk("EWTSA send cAddress=0x%x error!\n", regAddr);
return ret;
}
ret = i2c_master_recv( thisClient, (char*)pReadData, 1);
if(ret < 0)
{
- printk("EWTSAread *pReadData=0x%x error!\n", *pReadData);\r
+ printk("EWTSAread *pReadData=0x%x error!\n", *pReadData);
return ret;
}
return 1;
-}\r
-static int i2c_write_byte(struct i2c_client *thisClient, unsigned char regAddr, unsigned char writeData)\r
+}
+static int i2c_write_byte(struct i2c_client *thisClient, unsigned char regAddr, unsigned char writeData)
{
char write_data[2] = {0};
int ret=0;
-
+
write_data[0] = regAddr;
write_data[1] = writeData;
-
+
ret = i2c_master_send(thisClient, write_data, 2);
- if (ret < 0)
+ if (ret < 0)
{
ret = i2c_master_send(thisClient, write_data, 2);
- if (ret < 0)
+ if (ret < 0)
{
- printk("EWTSA send regAddr=0x%x error!\n", regAddr);\r
+ printk("EWTSA send regAddr=0x%x error!\n", regAddr);
return ret;
}
return 1;
}
-
+
return 1;
-}\r
-\r
-static int ewtsa_system_restart(struct i2c_client *client)\r
+}
+
+static int ewtsa_system_restart(struct i2c_client *client)
{
int err;
- char reg;\r
- char smpl , dlpf;\r
-\r
- err = i2c_write_byte(client, ( unsigned char)REG_SELF_O_C, ( unsigned char)SELF_O_C_DISABLE);\r
+ char reg;
+ char smpl , dlpf;
+
+ err = i2c_write_byte(client, ( unsigned char)REG_SELF_O_C, ( unsigned char)SELF_O_C_DISABLE);
if (err < 0) {
return err;
}
///Set SMPL register
- if (EWTSA_delay <= ( unsigned char)DELAY_THRES_2) {\r
- smpl = ( unsigned char)DELAY_INTMIN_THRES;\r
+ if (EWTSA_delay <= ( unsigned char)DELAY_THRES_2) {
+ smpl = ( unsigned char)DELAY_INTMIN_THRES;
}else{
- smpl = ( unsigned char)(EWTSA_delay - ( unsigned char)1);\r
- }\r
- err = i2c_write_byte(client, ( unsigned char)REG_SMPL, ( unsigned char)smpl);\r
+ smpl = ( unsigned char)(EWTSA_delay - ( unsigned char)1);
+ }
+ err = i2c_write_byte(client, ( unsigned char)REG_SMPL, ( unsigned char)smpl);
if (err < 0) {
return err;
}
///Set DLPF register
- if (EWTSA_delay >= ( unsigned char)DELAY_THRES_6){\r
- dlpf = ( unsigned char)DELAY_DLPF_6;\r
- }else if (EWTSA_delay >= ( unsigned char)DELAY_THRES_5) {\r
- dlpf = ( unsigned char)DELAY_DLPF_5;\r
- }else if (EWTSA_delay >= ( unsigned char)DELAY_THRES_4){\r
- dlpf = ( unsigned char)DELAY_DLPF_4;\r
- }else if (EWTSA_delay >= ( unsigned char)DELAY_THRES_3) {\r
- dlpf = ( unsigned char)DELAY_DLPF_3;\r
+ if (EWTSA_delay >= ( unsigned char)DELAY_THRES_6){
+ dlpf = ( unsigned char)DELAY_DLPF_6;
+ }else if (EWTSA_delay >= ( unsigned char)DELAY_THRES_5) {
+ dlpf = ( unsigned char)DELAY_DLPF_5;
+ }else if (EWTSA_delay >= ( unsigned char)DELAY_THRES_4){
+ dlpf = ( unsigned char)DELAY_DLPF_4;
+ }else if (EWTSA_delay >= ( unsigned char)DELAY_THRES_3) {
+ dlpf = ( unsigned char)DELAY_DLPF_3;
}else{
- dlpf = ( unsigned char)DELAY_DLPF_2;\r
+ dlpf = ( unsigned char)DELAY_DLPF_2;
}
- reg = ( unsigned char)(( unsigned char)(EWTSA_range << 3) | dlpf | ( unsigned char)0x80 ) ;\r
-\r
- err = i2c_write_byte(client, REG_FS_DLPF, reg);\r
+