1 /* drivers/input/sensors/access/akm8975.c
\r
3 * Copyright (C) 2012-2015 ROCKCHIP.
\r
4 * Author: luowei <lw@rock-chips.com>
\r
6 * This software is licensed under the terms of the GNU General Public
\r
7 * License version 2, as published by the Free Software Foundation, and
\r
8 * may be copied, distributed, and modified under those terms.
\r
10 * This program is distributed in the hope that it will be useful,
\r
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
\r
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
\r
13 * GNU General Public License for more details.
\r
16 #include <linux/interrupt.h>
\r
17 #include <linux/i2c.h>
\r
18 #include <linux/slab.h>
\r
19 #include <linux/irq.h>
\r
20 #include <linux/miscdevice.h>
\r
21 #include <linux/gpio.h>
\r
22 #include <asm/uaccess.h>
\r
23 #include <asm/atomic.h>
\r
24 #include <linux/delay.h>
\r
25 #include <linux/input.h>
\r
26 #include <linux/workqueue.h>
\r
27 #include <linux/freezer.h>
\r
28 #include <mach/gpio.h>
\r
29 #include <mach/board.h>
\r
30 #ifdef CONFIG_HAS_EARLYSUSPEND
\r
31 #include <linux/earlysuspend.h>
\r
33 #include <linux/akm8975.h>
\r
34 #include <linux/sensor-dev.h>
\r
36 #define SENSOR_DATA_SIZE 8
\r
39 #define SENSOR_DEBUG_TYPE SENSOR_TYPE_COMPASS
\r
40 #define DBG(x...) if(sensor->pdata->type == SENSOR_DEBUG_TYPE) printk(x)
\r
47 #define AK8975_DEVICE_ID 0x48
\r
48 static struct i2c_client *this_client;
\r
50 static atomic_t m_flag;
\r
51 static atomic_t a_flag;
\r
52 static atomic_t mv_flag;
\r
53 static atomic_t open_flag;
\r
54 static short akmd_delay = 100;
\r
55 static DECLARE_WAIT_QUEUE_HEAD(open_wq);
\r
58 /****************operate according to sensor chip:start************/
\r
60 static int sensor_active(struct i2c_client *client, int enable, int rate)
\r
62 struct sensor_private_data *sensor =
\r
63 (struct sensor_private_data *) i2c_get_clientdata(client);
\r
66 //sensor->ops->ctrl_data = sensor_read_reg(client, sensor->ops->ctrl_reg);
\r
68 //register setting according to chip datasheet
\r
71 sensor->ops->ctrl_data = AK8975_MODE_SNG_MEASURE;
\r
75 sensor->ops->ctrl_data = AK8975_MODE_POWERDOWN;
\r
78 DBG("%s:reg=0x%x,reg_ctrl=0x%x,enable=%d\n",__func__,sensor->ops->ctrl_reg, sensor->ops->ctrl_data, enable);
\r
79 result = sensor_write_reg(client, sensor->ops->ctrl_reg, sensor->ops->ctrl_data);
\r
81 printk("%s:fail to active sensor\n",__func__);
\r
87 static int sensor_init(struct i2c_client *client)
\r
89 struct sensor_private_data *sensor =
\r
90 (struct sensor_private_data *) i2c_get_clientdata(client);
\r
93 this_client = client;
\r
95 result = sensor->ops->active(client,0,0);
\r
98 printk("%s:line=%d,error\n",__func__,__LINE__);
\r
102 sensor->status_cur = SENSOR_OFF;
\r
104 sensor->ops->ctrl_data = 0;
\r
105 result = sensor_write_reg(client, sensor->ops->ctrl_reg, sensor->ops->ctrl_data);
\r
108 printk("%s:line=%d,error\n",__func__,__LINE__);
\r
112 DBG("%s:status_cur=%d\n",__func__, sensor->status_cur);
\r
116 static int sensor_report_value(struct i2c_client *client)
\r
118 struct sensor_private_data *sensor =
\r
119 (struct sensor_private_data *) i2c_get_clientdata(client);
\r
120 char buffer[8] = {0};
\r
121 unsigned char *stat;
\r
122 unsigned char *stat2;
\r
125 #ifdef SENSOR_DEBUG_TYPE
\r
128 if(sensor->ops->read_len < 8) //sensor->ops->read_len = 8
\r
130 printk("%s:lenth is error,len=%d\n",__func__,sensor->ops->read_len);
\r
134 memset(buffer, 0, 8);
\r
136 /* Data bytes from hardware xL, xH, yL, yH, zL, zH */
\r
138 *buffer = sensor->ops->read_reg;
\r
139 ret = sensor_rx_data(client, buffer, sensor->ops->read_len);
\r
145 stat2 = &buffer[7];
\r
149 * Measurement has been completed and data is ready to be read.
151 if ((*stat & 0x01) != 0x01) {
\r
152 DBG(KERN_ERR "%s:ST is not set\n",__func__);
\r
158 * occurs when data read is started outside of a readable period;
159 * data read would not be correct.
160 * Valid in continuous measurement mode only.
161 * In single measurement mode this error should not occour but we
162 * stil account for it and return an error, since the data would be
164 * DERR bit is self-clearing when ST2 register is read.
168 DBG(KERN_ERR "%s:compass data error\n",__func__);
\r
174 * the sum of the absolute values of all axis |X|+|Y|+|Z| < 2400uT.
175 * This is likely to happen in presence of an external magnetic
176 * disturbance; it indicates, the sensor data is incorrect and should
178 * An error is returned.
179 * HOFL bit clears when a new measurement starts.
183 DBG(KERN_ERR "%s:compass data overflow\n",__func__);
\r
187 /* »¥³âµØ»º´æÊý¾Ý. */
\r
188 mutex_lock(&sensor->data_mutex);
\r
189 memcpy(sensor->sensor_data, buffer, sensor->ops->read_len);
\r
190 mutex_unlock(&sensor->data_mutex);
\r
191 #ifdef SENSOR_DEBUG_TYPE
\r
192 DBG("%s:",__func__);
\r
193 for(i=0; i<sensor->ops->read_len; i++)
\r
194 DBG("%d,",buffer[i]);
\r
198 if((sensor->pdata->irq_enable)&& (sensor->ops->int_status_reg >= 0)) //read sensor intterupt status register
\r
201 value = sensor_read_reg(client, sensor->ops->int_status_reg);
\r
202 DBG("%s:sensor int status :0x%x\n",__func__,value);
\r
206 //trigger next measurement
\r
207 ret = sensor_write_reg(client, sensor->ops->ctrl_reg, sensor->ops->ctrl_data);
\r
210 printk(KERN_ERR "%s:fail to set ctrl_data:0x%x\n",__func__,sensor->ops->ctrl_data);
\r
217 static void compass_set_YPR(short *rbuf)
\r
219 struct sensor_private_data *sensor =
\r
220 (struct sensor_private_data *) i2c_get_clientdata(this_client);
\r
222 /* Report magnetic sensor information */
\r
223 if (atomic_read(&m_flag)) {
\r
224 input_report_abs(sensor->input_dev, ABS_RX, rbuf[0]);
\r
225 input_report_abs(sensor->input_dev, ABS_RY, rbuf[1]);
\r
226 input_report_abs(sensor->input_dev, ABS_RZ, rbuf[2]);
\r
227 input_report_abs(sensor->input_dev, ABS_RUDDER, rbuf[4]);
\r
228 DBG("%s:m_flag:x=%d,y=%d,z=%d,RUDDER=%d\n",__func__,rbuf[0], rbuf[1], rbuf[2], rbuf[4]);
\r
231 /* Report acceleration sensor information */
\r
232 if (atomic_read(&a_flag)) {
\r
233 input_report_abs(sensor->input_dev, ABS_X, rbuf[6]);
\r
234 input_report_abs(sensor->input_dev, ABS_Y, rbuf[7]);
\r
235 input_report_abs(sensor->input_dev, ABS_Z, rbuf[8]);
\r
236 input_report_abs(sensor->input_dev, ABS_WHEEL, rbuf[5]);
\r
238 DBG("%s:a_flag:x=%d,y=%d,z=%d,WHEEL=%d\n",__func__,rbuf[6], rbuf[7], rbuf[8], rbuf[5]);
\r
241 /* Report magnetic vector information */
\r
242 if (atomic_read(&mv_flag)) {
\r
243 input_report_abs(sensor->input_dev, ABS_HAT0X, rbuf[9]);
\r
244 input_report_abs(sensor->input_dev, ABS_HAT0Y, rbuf[10]);
\r
245 input_report_abs(sensor->input_dev, ABS_BRAKE, rbuf[11]);
\r
247 DBG("%s:mv_flag:x=%d,y=%d,BRAKE=%d\n",__func__,rbuf[9], rbuf[10], rbuf[11]);
\r
250 input_sync(sensor->input_dev);
\r
255 static int compass_aot_open(struct inode *inode, struct file *file)
\r
257 #ifdef SENSOR_DEBUG_TYPE
\r
258 struct sensor_private_data* sensor =
\r
259 (struct sensor_private_data *)i2c_get_clientdata(this_client);
\r
263 flag = atomic_read(&open_flag);
\r
266 atomic_set(&open_flag, 1);
\r
270 DBG("%s\n", __func__);
\r
275 static int compass_aot_release(struct inode *inode, struct file *file)
\r
277 #ifdef SENSOR_DEBUG_TYPE
\r
278 struct sensor_private_data* sensor =
\r
279 (struct sensor_private_data *)i2c_get_clientdata(this_client);
\r
281 //struct i2c_client *client = this_client;
\r
284 flag = atomic_read(&open_flag);
\r
287 atomic_set(&open_flag, 0);
\r
288 wake_up(&open_wq);
\r
291 DBG("%s\n", __func__);
\r
296 /* ioctl - I/O control */
\r
297 static long compass_aot_ioctl(struct file *file,
\r
298 unsigned int cmd, unsigned long arg)
\r
300 #ifdef SENSOR_DEBUG_TYPE
\r
301 struct sensor_private_data* sensor =
\r
302 (struct sensor_private_data *)i2c_get_clientdata(this_client);
\r
304 void __user *argp = (void __user *)arg;
\r
309 case ECS_IOCTL_APP_SET_MFLAG:
\r
310 case ECS_IOCTL_APP_SET_AFLAG:
\r
311 case ECS_IOCTL_APP_SET_MVFLAG:
\r
312 if (copy_from_user(&flag, argp, sizeof(flag))) {
\r
315 if (flag < 0 || flag > 1) {
\r
319 case ECS_IOCTL_APP_SET_DELAY:
\r
320 if (copy_from_user(&flag, argp, sizeof(flag))) {
\r
329 case ECS_IOCTL_APP_SET_MFLAG:
\r
330 atomic_set(&m_flag, flag);
\r
331 DBG("%s:ECS_IOCTL_APP_SET_MFLAG,flag=%d\n", __func__,flag);
\r
333 case ECS_IOCTL_APP_GET_MFLAG:
\r
334 flag = atomic_read(&m_flag);
\r
335 DBG("%s:ECS_IOCTL_APP_GET_MFLAG,flag=%d\n", __func__,flag);
\r
337 case ECS_IOCTL_APP_SET_AFLAG:
\r
338 atomic_set(&a_flag, flag);
\r
339 DBG("%s:ECS_IOCTL_APP_SET_AFLAG,flag=%d\n", __func__,flag);
\r
341 case ECS_IOCTL_APP_GET_AFLAG:
\r
342 flag = atomic_read(&a_flag);
\r
343 DBG("%s:ECS_IOCTL_APP_GET_AFLAG,flag=%d\n", __func__,flag);
\r
345 case ECS_IOCTL_APP_SET_MVFLAG:
\r
346 atomic_set(&mv_flag, flag);
\r
347 DBG("%s:ECS_IOCTL_APP_SET_MVFLAG,flag=%d\n", __func__,flag);
\r
349 case ECS_IOCTL_APP_GET_MVFLAG:
\r
350 flag = atomic_read(&mv_flag);
\r
351 DBG("%s:ECS_IOCTL_APP_GET_MVFLAG,flag=%d\n", __func__,flag);
\r
353 case ECS_IOCTL_APP_SET_DELAY:
\r
356 case ECS_IOCTL_APP_GET_DELAY:
\r
364 case ECS_IOCTL_APP_GET_MFLAG:
\r
365 case ECS_IOCTL_APP_GET_AFLAG:
\r
366 case ECS_IOCTL_APP_GET_MVFLAG:
\r
367 case ECS_IOCTL_APP_GET_DELAY:
\r
368 if (copy_to_user(argp, &flag, sizeof(flag))) {
\r
379 static int compass_dev_open(struct inode *inode, struct file *file)
\r
381 #ifdef SENSOR_DEBUG_TYPE
\r
382 struct sensor_private_data* sensor =
\r
383 (struct sensor_private_data *)i2c_get_clientdata(this_client);
\r
386 DBG("%s\n",__func__);
\r
392 static int compass_dev_release(struct inode *inode, struct file *file)
\r
394 #ifdef SENSOR_DEBUG_TYPE
\r
395 struct sensor_private_data* sensor =
\r
396 (struct sensor_private_data *)i2c_get_clientdata(this_client);
\r
399 DBG("%s\n",__func__);
\r
404 static int compass_akm_set_mode(struct i2c_client *client, char mode)
\r
406 struct sensor_private_data* sensor = (struct sensor_private_data *)i2c_get_clientdata(this_client);
\r
411 case AK8975_MODE_SNG_MEASURE:
\r
412 case AK8975_MODE_SELF_TEST:
\r
413 case AK8975_MODE_FUSE_ACCESS:
\r
414 if(sensor->status_cur == SENSOR_OFF)
\r
416 if(sensor->pdata->irq_enable)
\r
418 //DBG("%s:enable irq=%d\n",__func__,client->irq);
\r
419 //enable_irq(client->irq);
\r
423 schedule_delayed_work(&sensor->delaywork, msecs_to_jiffies(sensor->pdata->poll_delay_ms));
\r
426 sensor->status_cur = SENSOR_ON;
\r
431 case AK8975_MODE_POWERDOWN:
\r
432 if(sensor->status_cur == SENSOR_ON)
\r
434 if(sensor->pdata->irq_enable)
\r
436 //DBG("%s:disable irq=%d\n",__func__,client->irq);
\r
437 //disable_irq_nosync(client->irq);//disable irq
\r
440 cancel_delayed_work_sync(&sensor->delaywork);
\r
442 sensor->status_cur = SENSOR_OFF;
\r
450 case AK8975_MODE_SNG_MEASURE:
\r
451 result = sensor_write_reg(client, sensor->ops->ctrl_reg, AK8975_MODE_SNG_MEASURE);
\r
453 printk("%s:i2c error,mode=%d\n",__func__,mode);
\r
455 case AK8975_MODE_SELF_TEST:
\r
456 result = sensor_write_reg(client, sensor->ops->ctrl_reg, AK8975_MODE_SELF_TEST);
\r
458 printk("%s:i2c error,mode=%d\n",__func__,mode);
\r
460 case AK8975_MODE_FUSE_ACCESS:
\r
461 result = sensor_write_reg(client, sensor->ops->ctrl_reg, AK8975_MODE_FUSE_ACCESS);
\r
463 printk("%s:i2c error,mode=%d\n",__func__,mode);
\r
465 case AK8975_MODE_POWERDOWN:
\r
466 /* Set powerdown mode */
\r
467 result = sensor_write_reg(client, sensor->ops->ctrl_reg, AK8975_MODE_POWERDOWN);
\r
469 printk("%s:i2c error,mode=%d\n",__func__,mode);
\r
473 printk("%s: Unknown mode(%d)", __func__, mode);
\r
477 DBG("%s:mode=%d\n",__func__,mode);
\r
483 static int compass_akm_get_openstatus(void)
\r
485 wait_event_interruptible(open_wq, (atomic_read(&open_flag) != 0));
\r
486 return atomic_read(&open_flag);
\r
489 static int compass_akm_get_closestatus(void)
\r
491 wait_event_interruptible(open_wq, (atomic_read(&open_flag) <= 0));
\r
492 return atomic_read(&open_flag);
\r
496 /* ioctl - I/O control */
\r
497 static long compass_dev_ioctl(struct file *file,
\r
498 unsigned int cmd, unsigned long arg)
\r
500 struct sensor_private_data* sensor = (struct sensor_private_data *)i2c_get_clientdata(this_client);
\r
501 struct i2c_client *client = this_client;
\r
502 void __user *argp = (void __user *)arg;
\r
504 struct akm8975_platform_data compass;
\r
506 /* NOTE: In this function the size of "char" should be 1-byte. */
\r
507 char compass_data[SENSOR_DATA_SIZE];/* for GETDATA */
\r
508 char rwbuf[RWBUF_SIZE]; /* for READ/WRITE */
\r
509 char mode; /* for SET_MODE*/
\r
510 short value[12]; /* for SET_YPR */
\r
511 short delay; /* for GET_DELAY */
\r
512 int status; /* for OPEN/CLOSE_STATUS */
\r
513 int ret = -1; /* Return value. */
\r
516 case ECS_IOCTL_WRITE:
\r
517 case ECS_IOCTL_READ:
\r
518 if (argp == NULL) {
\r
521 if (copy_from_user(&rwbuf, argp, sizeof(rwbuf))) {
\r
525 case ECS_IOCTL_SET_MODE:
\r
526 if (argp == NULL) {
\r
529 if (copy_from_user(&mode, argp, sizeof(mode))) {
\r
533 case ECS_IOCTL_SET_YPR:
\r
534 if (argp == NULL) {
\r
537 if (copy_from_user(&value, argp, sizeof(value))) {
\r
546 case ECS_IOCTL_WRITE:
\r
547 DBG("%s:ECS_IOCTL_WRITE start\n",__func__);
\r
548 mutex_lock(&sensor->operation_mutex);
\r
549 if ((rwbuf[0] < 2) || (rwbuf[0] > (RWBUF_SIZE-1))) {
\r
550 mutex_unlock(&sensor->operation_mutex);
\r
553 ret = sensor_tx_data(client, &rwbuf[1], rwbuf[0]);
\r
555 mutex_unlock(&sensor->operation_mutex);
\r
556 printk("%s:fait to tx data\n",__func__);
\r
559 mutex_unlock(&sensor->operation_mutex);
\r
561 case ECS_IOCTL_READ:
\r
562 DBG("%s:ECS_IOCTL_READ start\n",__func__);
\r
563 mutex_lock(&sensor->operation_mutex);
\r
564 if ((rwbuf[0] < 1) || (rwbuf[0] > (RWBUF_SIZE-1))) {
\r
565 mutex_unlock(&sensor->operation_mutex);
\r
566 printk("%s:data is error\n",__func__);
\r
569 ret = sensor_rx_data(client, &rwbuf[1], rwbuf[0]);
\r
571 mutex_unlock(&sensor->operation_mutex);
\r
572 printk("%s:fait to rx data\n",__func__);
\r
575 mutex_unlock(&sensor->operation_mutex);
\r
577 case ECS_IOCTL_SET_MODE:
\r
578 DBG("%s:ECS_IOCTL_SET_MODE start\n",__func__);
\r
579 mutex_lock(&sensor->operation_mutex);
\r
580 if(sensor->ops->ctrl_data != mode)
\r
582 ret = compass_akm_set_mode(client, mode);
\r
584 printk("%s:fait to set mode\n",__func__);
\r
585 mutex_unlock(&sensor->operation_mutex);
\r
589 sensor->ops->ctrl_data = mode;
\r
591 mutex_unlock(&sensor->operation_mutex);
\r
593 case ECS_IOCTL_GETDATA:
\r
594 DBG("%s:ECS_IOCTL_GETDATA start\n",__func__);
\r
595 mutex_lock(&sensor->data_mutex);
\r
596 memcpy(compass_data, sensor->sensor_data, SENSOR_DATA_SIZE); //get data from buffer
\r
597 mutex_unlock(&sensor->data_mutex);
\r
599 case ECS_IOCTL_SET_YPR:
\r
600 DBG("%s:ECS_IOCTL_SET_YPR start\n",__func__);
\r
601 mutex_lock(&sensor->data_mutex);
\r
602 compass_set_YPR(value);
\r
603 mutex_unlock(&sensor->data_mutex);
\r
605 case ECS_IOCTL_GET_OPEN_STATUS:
\r
606 status = compass_akm_get_openstatus();
\r
607 DBG("%s:openstatus=%d\n",__func__,status);
\r
609 case ECS_IOCTL_GET_CLOSE_STATUS:
610 status = compass_akm_get_closestatus();
\r
611 DBG("%s:closestatus=%d\n",__func__,status);
\r
613 case ECS_IOCTL_GET_DELAY:
\r
614 delay = akmd_delay;
\r
616 case ECS_IOCTL_GET_PLATFORM_DATA:
\r
617 DBG("%s:ECS_IOCTL_GET_PLATFORM_DATA start\n",__func__);
\r
618 memcpy(compass.m_layout, sensor->pdata->m_layout, sizeof(sensor->pdata->m_layout));
\r
619 memcpy(compass.project_name, sensor->pdata->project_name, sizeof(sensor->pdata->project_name));
\r
620 ret = copy_to_user(argp, &compass, sizeof(compass));
\r
623 printk("%s:error,ret=%d\n",__FUNCTION__, ret);
\r
633 case ECS_IOCTL_READ:
\r
634 if (copy_to_user(argp, &rwbuf, rwbuf[0]+1)) {
\r
638 case ECS_IOCTL_GETDATA:
\r
639 if (copy_to_user(argp, &compass_data, sizeof(compass_data))) {
\r
643 case ECS_IOCTL_GET_OPEN_STATUS:
\r
644 case ECS_IOCTL_GET_CLOSE_STATUS:
\r
645 if (copy_to_user(argp, &status, sizeof(status))) {
\r
649 case ECS_IOCTL_GET_DELAY:
\r
650 if (copy_to_user(argp, &delay, sizeof(delay))) {
\r
662 static struct file_operations compass_aot_fops =
\r
664 .owner = THIS_MODULE,
\r
665 .unlocked_ioctl = compass_aot_ioctl,
\r
666 .open = compass_aot_open,
\r
667 .release = compass_aot_release,
\r
672 static struct miscdevice compass_aot_device =
\r
674 .minor = MISC_DYNAMIC_MINOR,
\r
675 .name = "akm8975_aot",
\r
676 .fops = &compass_aot_fops,
\r
680 static struct file_operations compass_dev_fops =
\r
682 .owner = THIS_MODULE,
\r
683 .open = compass_dev_open,
\r
684 .release = compass_dev_release,
\r
685 .unlocked_ioctl = compass_dev_ioctl,
\r
689 static struct miscdevice compass_dev_device =
\r
691 .minor = MISC_DYNAMIC_MINOR,
\r
692 .name = "akm8975_dev",
\r
693 .fops = &compass_dev_fops,
\r
696 struct sensor_operate akm8975_akm8975_ops = {
\r
698 .type = SENSOR_TYPE_COMPASS, //it is important
\r
699 .id_i2c = COMPASS_ID_AK8975,
\r
700 .read_reg = AK8975_REG_ST1, //read data
\r
701 .read_len = SENSOR_DATA_SIZE, //data length
\r
702 .id_reg = AK8975_REG_WIA, //read id
\r
703 .id_data = AK8975_DEVICE_ID,
\r
704 .precision = 8, //12 bits
\r
705 .ctrl_reg = AK8975_REG_CNTL, //enable or disable
\r
706 .int_status_reg = SENSOR_UNKNOW_DATA, //not exist
\r
707 .range = {-0xffff,0xffff},
\r
708 .trig = IRQF_TRIGGER_RISING, //if LEVEL interrupt then IRQF_ONESHOT
\r
709 .active = sensor_active,
\r
710 .init = sensor_init,
\r
711 .report = sensor_report_value,
\r
712 .misc_dev = &compass_dev_device, //private misc support
\r
715 /****************operate according to sensor chip:end************/
\r
717 //function name should not be changed
\r
718 static struct sensor_operate *compass_get_ops(void)
\r
720 return &akm8975_akm8975_ops;
\r
724 static int __init compass_akm8975_init(void)
\r
726 struct sensor_operate *ops = compass_get_ops();
\r
728 int type = ops->type;
\r
729 result = sensor_register_slave(type, NULL, NULL, compass_get_ops);
\r
731 result = misc_register(&compass_aot_device);
\r
733 printk("%s:fail to register misc device %s\n", __func__, compass_aot_device.name);
\r
737 /* As default, report all information */
\r
738 atomic_set(&m_flag, 1);
\r
739 atomic_set(&a_flag, 1);
\r
740 atomic_set(&mv_flag, 1);
\r
741 atomic_set(&open_flag, 0);
\r
742 init_waitqueue_head(&open_wq);
\r
744 DBG("%s\n",__func__);
\r
749 static void __exit compass_akm8975_exit(void)
\r
751 struct sensor_operate *ops = compass_get_ops();
\r
752 int type = ops->type;
\r
753 sensor_unregister_slave(type, NULL, NULL, compass_get_ops);
\r
757 module_init(compass_akm8975_init);
\r
758 module_exit(compass_akm8975_exit);
\r