-/* 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);
+
+