1 /* drivers/input/sensors/access/akm8963.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 <linux/of_gpio.h>
\r
29 #ifdef CONFIG_HAS_EARLYSUSPEND
\r
30 #include <linux/earlysuspend.h>
\r
32 #include <linux/sensor-dev.h>
\r
34 #define AKM_SENSOR_INFO_SIZE 2
35 #define AKM_SENSOR_CONF_SIZE 3
36 #define SENSOR_DATA_SIZE 8
\r
37 #define YPR_DATA_SIZE 12
\r
38 #define RWBUF_SIZE 16
\r
40 #define ACC_DATA_FLAG 0
\r
41 #define MAG_DATA_FLAG 1
\r
42 #define ORI_DATA_FLAG 2
\r
43 #define AKM_NUM_SENSORS 3
\r
45 #define ACC_DATA_READY (1<<(ACC_DATA_FLAG))
\r
46 #define MAG_DATA_READY (1<<(MAG_DATA_FLAG))
\r
47 #define ORI_DATA_READY (1<<(ORI_DATA_FLAG))
\r
49 /*! \name AK8963 constant definition
\r
51 Constant definitions of the AK8963.*/
\r
52 #define AK8963_MEASUREMENT_TIME_US 10000
\r
54 /*! \name AK8963 operation mode
\r
56 Defines an operation mode of the AK8963.*/
\r
58 #define AK8963_MODE_SNG_MEASURE 0x01
\r
59 #define AK8963_MODE_SELF_TEST 0x08
\r
60 #define AK8963_MODE_FUSE_ACCESS 0x0F
\r
61 #define AK8963_MODE_POWERDOWN 0x00
\r
65 /*! \name AK8963 register address
\r
67 Defines a register address of the AK8963.*/
\r
69 #define AK8963_REG_WIA 0x00
\r
70 #define AK8963_REG_INFO 0x01
\r
71 #define AK8963_REG_ST1 0x02
\r
72 #define AK8963_REG_HXL 0x03
\r
73 #define AK8963_REG_HXH 0x04
\r
74 #define AK8963_REG_HYL 0x05
\r
75 #define AK8963_REG_HYH 0x06
\r
76 #define AK8963_REG_HZL 0x07
\r
77 #define AK8963_REG_HZH 0x08
\r
78 #define AK8963_REG_ST2 0x09
\r
79 #define AK8963_REG_CNTL1 0x0A
\r
80 #define AK8963_REG_CNTL2 0x0B
\r
81 #define AK8963_REG_ASTC 0x0C
\r
82 #define AK8963_REG_TS1 0x0D
\r
83 #define AK8963_REG_TS2 0x0E
\r
84 #define AK8963_REG_I2CDIS 0x0F
\r
86 #define AK8963_WIA_VALUE 0x48
90 /*! \name AK8963 fuse-rom address
\r
92 Defines a read-only address of the fuse ROM of the AK8963.*/
\r
94 #define AK8963_FUSE_ASAX 0x10
\r
95 #define AK8963_FUSE_ASAY 0x11
\r
96 #define AK8963_FUSE_ASAZ 0x12
\r
99 #define AK8963_INFO_DATA (0x03<<3)
\r
102 #define COMPASS_IOCTL_MAGIC 'c'
\r
104 /* IOCTLs for AKM library */
\r
105 #define ECS_IOCTL_WRITE _IOW(COMPASS_IOCTL_MAGIC, 0x01, char*)
\r
106 #define ECS_IOCTL_READ _IOWR(COMPASS_IOCTL_MAGIC, 0x02, char*)
\r
107 #define ECS_IOCTL_RESET _IO(COMPASS_IOCTL_MAGIC, 0x03) /* NOT used in AK8975 */
\r
108 #define ECS_IOCTL_SET_MODE _IOW(COMPASS_IOCTL_MAGIC, 0x04, short)
\r
109 #define ECS_IOCTL_GETDATA _IOR(COMPASS_IOCTL_MAGIC, 0x05, char[SENSOR_DATA_SIZE])
\r
110 #define ECS_IOCTL_SET_YPR _IOW(COMPASS_IOCTL_MAGIC, 0x06, short[12])
\r
111 #define ECS_IOCTL_GET_OPEN_STATUS _IOR(COMPASS_IOCTL_MAGIC, 0x07, int)
\r
112 #define ECS_IOCTL_GET_CLOSE_STATUS _IOR(COMPASS_IOCTL_MAGIC, 0x08, int)
\r
113 #define ECS_IOCTL_GET_LAYOUT _IOR(COMPASS_IOCTL_MAGIC, 0x09, char)
\r
114 #define ECS_IOCTL_GET_ACCEL _IOR(COMPASS_IOCTL_MAGIC, 0x0A, short[3])
\r
115 #define ECS_IOCTL_GET_OUTBIT _IOR(COMPASS_IOCTL_MAGIC, 0x0B, char)
\r
116 #define ECS_IOCTL_GET_DELAY _IOR(COMPASS_IOCTL_MAGIC, 0x30, short)
\r
117 #define ECS_IOCTL_GET_PROJECT_NAME _IOR(COMPASS_IOCTL_MAGIC, 0x0D, char[64])
\r
118 #define ECS_IOCTL_GET_MATRIX _IOR(COMPASS_IOCTL_MAGIC, 0x0E, short [4][3][3])
\r
119 #define ECS_IOCTL_GET_PLATFORM_DATA _IOR(COMPASS_IOCTL_MAGIC, 0x0E, struct akm_platform_data)
\r
120 #define ECS_IOCTL_GET_INFO _IOR(COMPASS_IOCTL_MAGIC, 0x27, unsigned char[AKM_SENSOR_INFO_SIZE])
121 #define ECS_IOCTL_GET_CONF _IOR(COMPASS_IOCTL_MAGIC, 0x28, unsigned char[AKM_SENSOR_CONF_SIZE])
123 #define AK8963_DEVICE_ID 0x48
\r
124 static struct i2c_client *this_client;
\r
125 static struct miscdevice compass_dev_device;
\r
127 static short g_akm_rbuf[12];
\r
130 /****************operate according to sensor chip:start************/
\r
132 static int sensor_active(struct i2c_client *client, int enable, int rate)
\r
134 struct sensor_private_data *sensor =
\r
135 (struct sensor_private_data *) i2c_get_clientdata(client);
\r
138 //sensor->ops->ctrl_data = sensor_read_reg(client, sensor->ops->ctrl_reg);
\r
140 //register setting according to chip datasheet
\r
143 sensor->ops->ctrl_data = AK8963_MODE_SNG_MEASURE;
\r
147 sensor->ops->ctrl_data = AK8963_MODE_POWERDOWN;
\r
150 DBG("%s:reg=0x%x,reg_ctrl=0x%x,enable=%d\n",__func__,sensor->ops->ctrl_reg, sensor->ops->ctrl_data, enable);
\r
151 result = sensor_write_reg(client, sensor->ops->ctrl_reg, sensor->ops->ctrl_data);
\r
153 printk("%s:fail to active sensor\n",__func__);
\r
159 static int sensor_init(struct i2c_client *client)
\r
161 struct sensor_private_data *sensor =
\r
162 (struct sensor_private_data *) i2c_get_clientdata(client);
\r
166 this_client = client;
\r
168 result = sensor->ops->active(client,0,0);
\r
171 printk("%s:line=%d,error\n",__func__,__LINE__);
\r
175 sensor->status_cur = SENSOR_OFF;
\r
177 info = sensor_read_reg(client, AK8963_REG_INFO);
\r
178 if((info & (0x0f<<3)) != AK8963_INFO_DATA)
\r
180 printk("%s:info=0x%x,it is not %s\n",__func__, info, sensor->ops->name);
\r
184 result = misc_register(&compass_dev_device);
\r
186 printk("%s:fail to register misc device %s\n", __func__, compass_dev_device.name);
\r
190 DBG("%s:status_cur=%d\n",__func__, sensor->status_cur);
\r
194 static int sensor_report_value(struct i2c_client *client)
\r
196 struct sensor_private_data *sensor =
\r
197 (struct sensor_private_data *) i2c_get_clientdata(client);
\r
198 char buffer[8] = {0};
\r
199 unsigned char *stat;
\r
200 unsigned char *stat2;
\r
205 if(sensor->ops->read_len < 8) //sensor->ops->read_len = 8
\r
207 printk("%s:lenth is error,len=%d\n",__func__,sensor->ops->read_len);
\r
211 memset(buffer, 0, 8);
\r
213 /* Data bytes from hardware xL, xH, yL, yH, zL, zH */
\r
215 *buffer = sensor->ops->read_reg;
\r
216 ret = sensor_rx_data(client, buffer, sensor->ops->read_len);
\r
222 stat2 = &buffer[7];
\r
226 * Measurement has been completed and data is ready to be read.
228 if ((*stat & 0x01) != 0x01) {
\r
229 DBG(KERN_ERR "%s:ST is not set\n",__func__);
\r
235 * occurs when data read is started outside of a readable period;
236 * data read would not be correct.
237 * Valid in continuous measurement mode only.
238 * In single measurement mode this error should not occour but we
239 * stil account for it and return an error, since the data would be
241 * DERR bit is self-clearing when ST2 register is read.
245 DBG(KERN_ERR "%s:compass data error\n",__func__);
\r
251 * the sum of the absolute values of all axis |X|+|Y|+|Z| < 2400uT.
252 * This is likely to happen in presence of an external magnetic
253 * disturbance; it indicates, the sensor data is incorrect and should
255 * An error is returned.
256 * HOFL bit clears when a new measurement starts.
260 DBG(KERN_ERR "%s:compass data overflow\n",__func__);
\r
264 /* »¥³âµØ»º´æÊý¾Ý. */
\r
265 mutex_lock(&sensor->data_mutex);
\r
266 memcpy(sensor->sensor_data, buffer, sensor->ops->read_len);
\r
267 mutex_unlock(&sensor->data_mutex);
\r
268 DBG("%s:",__func__);
\r
269 for(i=0; i<sensor->ops->read_len; i++)
\r
270 DBG("0x%x,",buffer[i]);
\r
273 if((sensor->pdata->irq_enable)&& (sensor->ops->int_status_reg >= 0)) //read sensor intterupt status register
\r
276 value = sensor_read_reg(client, sensor->ops->int_status_reg);
\r
277 DBG("%s:sensor int status :0x%x\n",__func__,value);
\r
281 //trigger next measurement
\r
282 ret = sensor_write_reg(client, sensor->ops->ctrl_reg, sensor->ops->ctrl_data);
\r
285 printk(KERN_ERR "%s:fail to set ctrl_data:0x%x\n",__func__,sensor->ops->ctrl_data);
\r
292 static void compass_set_YPR(int *rbuf)
\r
294 struct sensor_private_data *sensor =
\r
295 (struct sensor_private_data *) i2c_get_clientdata(this_client);
\r
297 /* No events are reported */
\r
299 printk("%s:Don't waste a time.",__func__);
\r
303 DBG("%s:buf[0]=0x%x\n",__func__, rbuf[0]);
\r
305 /* Report magnetic sensor information */
\r
306 if (atomic_read(&sensor->flags.m_flag) && (rbuf[0] & MAG_DATA_READY)) {
307 input_report_abs(sensor->input_dev, ABS_RX, rbuf[5]);
308 input_report_abs(sensor->input_dev, ABS_RY, rbuf[6]);
309 input_report_abs(sensor->input_dev, ABS_RZ, rbuf[7]);
310 input_report_abs(sensor->input_dev, ABS_RUDDER, rbuf[8]);
311 DBG("%s:m_flag:x=%d,y=%d,z=%d,RUDDER=%d\n", __func__, rbuf[5], rbuf[6], rbuf[7], rbuf[8]);
314 /* Report acceleration sensor information */
\r
315 if (atomic_read(&sensor->flags.a_flag) && (rbuf[0] & ACC_DATA_READY)) {
\r
316 input_report_abs(sensor->input_dev, ABS_X, rbuf[1]);
\r
317 input_report_abs(sensor->input_dev, ABS_Y, rbuf[2]);
\r
318 input_report_abs(sensor->input_dev, ABS_Z, rbuf[3]);
\r
319 input_report_abs(sensor->input_dev, ABS_WHEEL, rbuf[4]);
\r
321 DBG("%s:a_flag:x=%d,y=%d,z=%d,WHEEL=%d\n",__func__,rbuf[1], rbuf[2], rbuf[3], rbuf[4]);
\r
324 /* Report magnetic vector information */
\r
325 if (atomic_read(&sensor->flags.mv_flag) && (rbuf[0] & ORI_DATA_READY)) {
326 input_report_abs(sensor->input_dev, ABS_HAT0X, rbuf[9]);
327 input_report_abs(sensor->input_dev, ABS_HAT0Y, rbuf[10]);
328 input_report_abs(sensor->input_dev, ABS_BRAKE, rbuf[11]);
329 input_report_abs(sensor->input_dev, ABS_HAT1X, rbuf[12]);
331 DBG("%s:mv_flag:x=%d,y=%d,z=%d,status=%d\n", __func__, rbuf[9], rbuf[10], rbuf[11], rbuf[12]);
334 input_sync(sensor->input_dev);
\r
336 memcpy(g_akm_rbuf, rbuf, 12); //used for ECS_IOCTL_GET_ACCEL
\r
341 static int compass_dev_open(struct inode *inode, struct file *file)
\r
344 DBG("%s\n",__func__);
\r
350 static int compass_dev_release(struct inode *inode, struct file *file)
\r
353 DBG("%s\n",__func__);
\r
358 static int compass_akm_set_mode(struct i2c_client *client, char mode)
\r
360 struct sensor_private_data* sensor = (struct sensor_private_data *)i2c_get_clientdata(this_client);
\r
363 switch(mode & 0x0f)
\r
365 case AK8963_MODE_SNG_MEASURE:
\r
366 case AK8963_MODE_SELF_TEST:
\r
367 case AK8963_MODE_FUSE_ACCESS:
\r
368 if(sensor->status_cur == SENSOR_OFF)
\r
370 if(sensor->pdata->irq_enable)
\r
372 //DBG("%s:enable irq=%d\n",__func__,client->irq);
\r
373 //enable_irq(client->irq);
\r
377 schedule_delayed_work(&sensor->delaywork, msecs_to_jiffies(sensor->pdata->poll_delay_ms));
\r
380 sensor->status_cur = SENSOR_ON;
\r
385 case AK8963_MODE_POWERDOWN:
\r
386 if(sensor->status_cur == SENSOR_ON)
\r
388 if(sensor->pdata->irq_enable)
\r
390 //DBG("%s:disable irq=%d\n",__func__,client->irq);
\r
391 //disable_irq_nosync(client->irq);//disable irq
\r
394 cancel_delayed_work_sync(&sensor->delaywork);
\r
396 sensor->status_cur = SENSOR_OFF;
\r
402 switch(mode & 0x0f)
\r
404 case AK8963_MODE_SNG_MEASURE:
\r
405 result = sensor_write_reg(client, sensor->ops->ctrl_reg, mode);
\r
407 printk("%s:i2c error,mode=%d\n",__func__,mode);
\r
409 case AK8963_MODE_SELF_TEST:
\r
410 result = sensor_write_reg(client, sensor->ops->ctrl_reg, mode);
\r
412 printk("%s:i2c error,mode=%d\n",__func__,mode);
\r
414 case AK8963_MODE_FUSE_ACCESS:
\r
415 result = sensor_write_reg(client, sensor->ops->ctrl_reg, mode);
\r
417 printk("%s:i2c error,mode=%d\n",__func__,mode);
\r
419 case AK8963_MODE_POWERDOWN:
\r
420 /* Set powerdown mode */
\r
421 result = sensor_write_reg(client, sensor->ops->ctrl_reg, AK8963_MODE_POWERDOWN);
\r
423 printk("%s:i2c error,mode=%d\n",__func__,mode);
\r
427 printk("%s: Unknown mode(%d)", __func__, mode);
\r
431 DBG("%s:mode=0x%x\n",__func__,mode);
\r
436 static int compass_akm_reset(struct i2c_client *client)
\r
438 struct sensor_private_data* sensor = (struct sensor_private_data *)i2c_get_clientdata(this_client);
\r
441 if(sensor->pdata->reset_pin > 0)
\r
443 gpio_direction_output(sensor->pdata->reset_pin, GPIO_LOW);
\r
445 gpio_direction_output(sensor->pdata->reset_pin, GPIO_HIGH);
\r
449 /* Set measure mode */
\r
450 result = sensor_write_reg(client, AK8963_REG_CNTL2, AK8963_MODE_SNG_MEASURE);
\r
452 printk("%s:fail to Set measure mode\n",__func__);
\r
463 static int compass_akm_get_openstatus(void)
\r
465 struct sensor_private_data* sensor = (struct sensor_private_data *)i2c_get_clientdata(this_client);
\r
466 wait_event_interruptible(sensor->flags.open_wq, (atomic_read(&sensor->flags.open_flag) != 0));
\r
467 return atomic_read(&sensor->flags.open_flag);
\r
470 static int compass_akm_get_closestatus(void)
\r
472 struct sensor_private_data* sensor = (struct sensor_private_data *)i2c_get_clientdata(this_client);
\r
473 wait_event_interruptible(sensor->flags.open_wq, (atomic_read(&sensor->flags.open_flag) <= 0));
\r
474 return atomic_read(&sensor->flags.open_flag);
\r
478 /* ioctl - I/O control */
\r
479 static long compass_dev_ioctl(struct file *file,
\r
480 unsigned int cmd, unsigned long arg)
\r
482 struct sensor_private_data* sensor = (struct sensor_private_data *)i2c_get_clientdata(this_client);
\r
483 struct i2c_client *client = this_client;
\r
484 void __user *argp = (void __user *)arg;
\r
486 struct akm_platform_data compass;
\r
487 unsigned char sense_info[AKM_SENSOR_INFO_SIZE];
488 unsigned char sense_conf[AKM_SENSOR_CONF_SIZE];
490 /* NOTE: In this function the size of "char" should be 1-byte. */
\r
491 char compass_data[SENSOR_DATA_SIZE]; /* for GETDATA */
\r
492 char rwbuf[RWBUF_SIZE]; /* for READ/WRITE */
\r
493 char mode; /* for SET_MODE*/
\r
494 int value[12]; /* for SET_YPR */
\r
495 int status; /* for OPEN/CLOSE_STATUS */
\r
496 int ret = -1; /* Return value. */
\r
498 //int8_t sensor_buf[SENSOR_DATA_SIZE]; /* for GETDATA */
\r
499 //int32_t ypr_buf[YPR_DATA_SIZE]; /* for SET_YPR */
\r
500 int16_t acc_buf[3]; /* for GET_ACCEL */
\r
501 int64_t delay[AKM_NUM_SENSORS]; /* for GET_DELAY */
\r
503 char layout; /* for GET_LAYOUT */
\r
504 char outbit; /* for GET_OUTBIT */
\r
507 case ECS_IOCTL_WRITE:
\r
508 case ECS_IOCTL_READ:
\r
509 if (argp == NULL) {
\r
512 if (copy_from_user(&rwbuf, argp, sizeof(rwbuf))) {
\r
516 case ECS_IOCTL_SET_MODE:
\r
517 if (argp == NULL) {
\r
520 if (copy_from_user(&mode, argp, sizeof(mode))) {
\r
524 case ECS_IOCTL_SET_YPR:
\r
525 if (argp == NULL) {
\r
528 if (copy_from_user(&value, argp, sizeof(value))) {
\r
532 case ECS_IOCTL_GET_INFO:
533 case ECS_IOCTL_GET_CONF:
534 case ECS_IOCTL_GETDATA:
\r
535 case ECS_IOCTL_GET_OPEN_STATUS:
\r
536 case ECS_IOCTL_GET_CLOSE_STATUS:
\r
537 case ECS_IOCTL_GET_DELAY:
\r
538 case ECS_IOCTL_GET_LAYOUT:
\r
539 case ECS_IOCTL_GET_OUTBIT:
\r
540 case ECS_IOCTL_GET_ACCEL:
\r
541 /* Just check buffer pointer */
\r
542 if (argp == NULL) {
\r
543 printk("%s:invalid argument\n",__func__);
\r
552 case ECS_IOCTL_GET_INFO:
553 sense_info[0] = AK8963_REG_WIA;
554 mutex_lock(&sensor->operation_mutex);
555 ret = sensor_rx_data(client, &sense_info[0], AKM_SENSOR_INFO_SIZE);
556 mutex_unlock(&sensor->operation_mutex);
558 printk("%s:fait to get sense_info\n", __func__);
561 /* Check read data */
562 if (sense_info[0] != AK8963_WIA_VALUE) {
563 dev_err(&client->dev,
564 "%s: The device is not AKM Compass.", __func__);
568 case ECS_IOCTL_GET_CONF:
569 sense_conf[0] = AK8963_FUSE_ASAX;
570 mutex_lock(&sensor->operation_mutex);
571 ret = sensor_rx_data(client, &sense_conf[0], AKM_SENSOR_CONF_SIZE);
572 mutex_unlock(&sensor->operation_mutex);
574 printk("%s:fait to get sense_conf\n", __func__);
578 case ECS_IOCTL_WRITE:
\r
579 DBG("%s:ECS_IOCTL_WRITE start\n",__func__);
\r
580 mutex_lock(&sensor->operation_mutex);
\r
581 if ((rwbuf[0] < 2) || (rwbuf[0] > (RWBUF_SIZE-1))) {
\r
582 mutex_unlock(&sensor->operation_mutex);
\r
585 ret = sensor_tx_data(client, &rwbuf[1], rwbuf[0]);
\r
587 mutex_unlock(&sensor->operation_mutex);
\r
588 printk("%s:fait to tx data\n",__func__);
\r
591 mutex_unlock(&sensor->operation_mutex);
\r
593 case ECS_IOCTL_READ:
\r
594 DBG("%s:ECS_IOCTL_READ start\n",__func__);
\r
595 mutex_lock(&sensor->operation_mutex);
\r
596 if ((rwbuf[0] < 1) || (rwbuf[0] > (RWBUF_SIZE-1))) {
\r
597 mutex_unlock(&sensor->operation_mutex);
\r
598 printk("%s:data is error\n",__func__);
\r
601 ret = sensor_rx_data(client, &rwbuf[1], rwbuf[0]);
\r
603 mutex_unlock(&sensor->operation_mutex);
\r
604 printk("%s:fait to rx data\n",__func__);
\r
607 mutex_unlock(&sensor->operation_mutex);
\r
609 case ECS_IOCTL_SET_MODE:
\r
610 DBG("%s:ECS_IOCTL_SET_MODE start\n",__func__);
\r
611 mutex_lock(&sensor->operation_mutex);
\r
612 if(sensor->ops->ctrl_data != mode)
\r
614 ret = compass_akm_set_mode(client, mode);
\r
616 printk("%s:fait to set mode\n",__func__);
\r
617 mutex_unlock(&sensor->operation_mutex);
\r
621 sensor->ops->ctrl_data = mode;
\r
623 mutex_unlock(&sensor->operation_mutex);
\r
625 case ECS_IOCTL_GETDATA:
\r
626 DBG("%s:ECS_IOCTL_GETDATA start\n",__func__);
\r
627 mutex_lock(&sensor->data_mutex);
\r
628 memcpy(compass_data, sensor->sensor_data, SENSOR_DATA_SIZE); //get data from buffer
\r
629 mutex_unlock(&sensor->data_mutex);
\r
631 case ECS_IOCTL_SET_YPR:
\r
632 DBG("%s:ECS_IOCTL_SET_YPR start\n",__func__);
\r
633 mutex_lock(&sensor->data_mutex);
\r
634 compass_set_YPR(value);
\r
635 mutex_unlock(&sensor->data_mutex);
\r
637 case ECS_IOCTL_GET_OPEN_STATUS:
\r
638 status = compass_akm_get_openstatus();
\r
639 DBG("%s:openstatus=%d\n",__func__,status);
\r
641 case ECS_IOCTL_GET_CLOSE_STATUS:
\r
642 status = compass_akm_get_closestatus();
\r
643 DBG("%s:closestatus=%d\n",__func__,status);
\r
645 case ECS_IOCTL_GET_DELAY:
\r
646 DBG("%s:ECS_IOCTL_GET_DELAY start\n",__func__);
\r
647 mutex_lock(&sensor->operation_mutex);
\r
648 delay[0] = sensor->flags.delay;
\r
649 delay[1] = sensor->flags.delay;
\r
650 delay[2] = sensor->flags.delay;
\r
651 mutex_unlock(&sensor->operation_mutex);
\r
654 case ECS_IOCTL_GET_PLATFORM_DATA:
\r
655 DBG("%s:ECS_IOCTL_GET_PLATFORM_DATA start\n",__func__);
\r
656 //memcpy(compass.m_layout, sensor->pdata->m_layout, sizeof(sensor->pdata->m_layout));
\r
657 //memcpy(compass.project_name, sensor->pdata->project_name, sizeof(sensor->pdata->project_name));
\r
658 ret = copy_to_user(argp, &compass, sizeof(compass));
\r
661 printk("%s:error,ret=%d\n",__FUNCTION__, ret);
\r
665 case ECS_IOCTL_GET_LAYOUT:
\r
666 DBG("%s:ECS_IOCTL_GET_LAYOUT start\n",__func__);
\r
667 layout = sensor->pdata->layout;
\r
669 case ECS_IOCTL_GET_OUTBIT:
\r
670 DBG("%s:ECS_IOCTL_GET_OUTBIT start\n",__func__);
\r
671 outbit = 1; //sensor->pdata->outbit;
\r
673 case ECS_IOCTL_RESET:
\r
674 DBG("%s:ECS_IOCTL_RESET start\n",__func__);
\r
675 ret = compass_akm_reset(client);
\r
679 case ECS_IOCTL_GET_ACCEL:
\r
680 DBG("%s:ECS_IOCTL_GET_ACCEL start,no accel data\n",__func__);
\r
681 mutex_lock(&sensor->operation_mutex);
\r
682 acc_buf[0] = g_akm_rbuf[6];
\r
683 acc_buf[1] = g_akm_rbuf[7];
\r
684 acc_buf[2] = g_akm_rbuf[8];
\r
685 mutex_unlock(&sensor->operation_mutex);
\r
693 case ECS_IOCTL_READ:
\r
694 if (copy_to_user(argp, &rwbuf, rwbuf[0]+1)) {
\r
698 case ECS_IOCTL_GETDATA:
\r
699 if (copy_to_user(argp, &compass_data, sizeof(compass_data))) {
\r
703 case ECS_IOCTL_GET_OPEN_STATUS:
\r
704 case ECS_IOCTL_GET_CLOSE_STATUS:
\r
705 if (copy_to_user(argp, &status, sizeof(status))) {
\r
709 case ECS_IOCTL_GET_DELAY:
\r
710 if (copy_to_user(argp, &delay, sizeof(delay))) {
\r
714 case ECS_IOCTL_GET_LAYOUT:
\r
715 if (copy_to_user(argp, &layout, sizeof(layout))) {
\r
716 printk("%s:error:%d\n",__FUNCTION__,__LINE__);
\r
720 case ECS_IOCTL_GET_OUTBIT:
\r
721 if (copy_to_user(argp, &outbit, sizeof(outbit))) {
\r
722 printk("%s:error:%d\n",__FUNCTION__,__LINE__);
\r
726 case ECS_IOCTL_GET_ACCEL:
\r
727 if (copy_to_user(argp, &acc_buf, sizeof(acc_buf))) {
\r
728 printk("%s:error:%d\n",__FUNCTION__,__LINE__);
\r
732 case ECS_IOCTL_GET_INFO:
733 if (copy_to_user(argp, &sense_info, sizeof(sense_info))) {
734 printk("%s:error:%d\n", __FUNCTION__, __LINE__);
738 case ECS_IOCTL_GET_CONF:
739 if (copy_to_user(argp, &sense_conf, sizeof(sense_conf))) {
740 printk("%s:error:%d\n", __FUNCTION__, __LINE__);
751 static struct file_operations compass_dev_fops =
\r
753 .owner = THIS_MODULE,
\r
754 .open = compass_dev_open,
\r
755 .release = compass_dev_release,
\r
756 .unlocked_ioctl = compass_dev_ioctl,
\r
760 static struct miscdevice compass_dev_device =
\r
762 .minor = MISC_DYNAMIC_MINOR,
\r
763 .name = "akm8963_dev",
\r
764 .fops = &compass_dev_fops,
\r
767 struct sensor_operate compass_akm8963_ops = {
\r
769 .type = SENSOR_TYPE_COMPASS, //it is important
\r
770 .id_i2c = COMPASS_ID_AK8963,
\r
771 .read_reg = AK8963_REG_ST1, //read data
\r
772 .read_len = SENSOR_DATA_SIZE, //data length
\r
773 .id_reg = AK8963_REG_WIA, //read id
\r
774 .id_data = AK8963_DEVICE_ID,
\r
775 .precision = 8, //12 bits
\r
776 .ctrl_reg = AK8963_REG_CNTL1, //enable or disable
\r
777 .int_status_reg = SENSOR_UNKNOW_DATA, //not exist
\r
778 .range = {-0xffff,0xffff},
\r
779 .trig = IRQF_TRIGGER_RISING, //if LEVEL interrupt then IRQF_ONESHOT
\r
780 .active = sensor_active,
\r
781 .init = sensor_init,
\r
782 .report = sensor_report_value,
\r
783 .misc_dev = NULL, //private misc support
\r
786 /****************operate according to sensor chip:end************/
\r
788 //function name should not be changed
\r
789 static struct sensor_operate *compass_get_ops(void)
\r
791 return &compass_akm8963_ops;
\r
795 static int __init compass_akm8963_init(void)
\r
797 struct sensor_operate *ops = compass_get_ops();
\r
799 int type = ops->type;
\r
800 result = sensor_register_slave(type, NULL, NULL, compass_get_ops);
\r
805 static void __exit compass_akm8963_exit(void)
\r
807 struct sensor_operate *ops = compass_get_ops();
\r
808 int type = ops->type;
\r
809 sensor_unregister_slave(type, NULL, NULL, compass_get_ops);
\r
813 module_init(compass_akm8963_init);
\r
814 module_exit(compass_akm8963_exit);
\r