sensor:mask some debug information
[firefly-linux-kernel-4.4.55.git] / drivers / input / sensors / compass / ak8975.c
1 /* drivers/input/sensors/access/akm8975.c\r
2  *\r
3  * Copyright (C) 2012-2015 ROCKCHIP.\r
4  * Author: luowei <lw@rock-chips.com>\r
5  *\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
9  *\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
14  *\r
15  */\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
32 #endif\r
33 #include <linux/akm8975.h>\r
34 #include <linux/sensor-dev.h>\r
35 \r
36 #define SENSOR_DATA_SIZE                8\r
37 \r
38 #if 0\r
39 #define SENSOR_DEBUG_TYPE SENSOR_TYPE_COMPASS\r
40 #define DBG(x...) if(sensor->pdata->type == SENSOR_DEBUG_TYPE) printk(x)\r
41 #else\r
42 #define DBG(x...)\r
43 #endif\r
44 \r
45 \r
46 \r
47 #define AK8975_DEVICE_ID                0x48\r
48 static struct i2c_client *this_client;\r
49 \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
56 \r
57 \r
58 /****************operate according to sensor chip:start************/\r
59 \r
60 static int sensor_active(struct i2c_client *client, int enable, int rate)\r
61 {\r
62         struct sensor_private_data *sensor =\r
63             (struct sensor_private_data *) i2c_get_clientdata(client);  \r
64         int result = 0;\r
65                 \r
66         //sensor->ops->ctrl_data = sensor_read_reg(client, sensor->ops->ctrl_reg);\r
67         \r
68         //register setting according to chip datasheet          \r
69         if(enable)\r
70         {       \r
71                 sensor->ops->ctrl_data = AK8975_MODE_SNG_MEASURE;       \r
72         }\r
73         else\r
74         {\r
75                 sensor->ops->ctrl_data = AK8975_MODE_POWERDOWN;\r
76         }\r
77 \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
80         if(result)\r
81                 printk("%s:fail to active sensor\n",__func__);\r
82         \r
83         return result;\r
84 \r
85 }\r
86 \r
87 static int sensor_init(struct i2c_client *client)\r
88 {       \r
89         struct sensor_private_data *sensor =\r
90             (struct sensor_private_data *) i2c_get_clientdata(client);  \r
91         int result = 0;\r
92 \r
93         this_client = client;   \r
94 \r
95         result = sensor->ops->active(client,0,0);\r
96         if(result)\r
97         {\r
98                 printk("%s:line=%d,error\n",__func__,__LINE__);\r
99                 return result;\r
100         }\r
101         \r
102         sensor->status_cur = SENSOR_OFF;\r
103 #if 0   \r
104         sensor->ops->ctrl_data = 0;\r
105         result = sensor_write_reg(client, sensor->ops->ctrl_reg, sensor->ops->ctrl_data);\r
106         if(result)\r
107         {\r
108                 printk("%s:line=%d,error\n",__func__,__LINE__);\r
109                 return result;\r
110         }\r
111 #endif\r
112         DBG("%s:status_cur=%d\n",__func__, sensor->status_cur);\r
113         return result;\r
114 }\r
115 \r
116 static int sensor_report_value(struct i2c_client *client)\r
117 {\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
123         int ret = 0;    \r
124         char value = 0;\r
125 #ifdef SENSOR_DEBUG_TYPE        \r
126         int i;\r
127 #endif                  \r
128         if(sensor->ops->read_len < 8)   //sensor->ops->read_len = 8\r
129         {\r
130                 printk("%s:lenth is error,len=%d\n",__func__,sensor->ops->read_len);\r
131                 return -1;\r
132         }\r
133         \r
134         memset(buffer, 0, 8);\r
135         \r
136         /* Data bytes from hardware xL, xH, yL, yH, zL, zH */   \r
137         do {\r
138                 *buffer = sensor->ops->read_reg;\r
139                 ret = sensor_rx_data(client, buffer, sensor->ops->read_len);\r
140                 if (ret < 0)\r
141                 return ret;\r
142         } while (0);\r
143 \r
144         stat = &buffer[0];\r
145         stat2 = &buffer[7];\r
146         \r
147         /*\r
148          * ST : data ready -
149          * Measurement has been completed and data is ready to be read.
150          */\r
151         if ((*stat & 0x01) != 0x01) {\r
152                 DBG(KERN_ERR "%s:ST is not set\n",__func__);\r
153                 return -1;\r
154         }\r
155
156         /*
157          * ST2 : data error -
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
163          * corrupted.
164          * DERR bit is self-clearing when ST2 register is read.
165          */
166         if (*stat2 & 0x04)\r
167         {\r
168                 DBG(KERN_ERR "%s:compass data error\n",__func__);\r
169                 return -2;\r
170         }\r
171         \r
172         /*
173          * ST2 : overflow -
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
177          * be ignored.
178          * An error is returned.
179          * HOFL bit clears when a new measurement starts.
180          */
181         if (*stat2 & 0x08)\r
182         {       \r
183                 DBG(KERN_ERR "%s:compass data overflow\n",__func__);\r
184                 return -3;\r
185         }\r
186         \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
195         DBG("\n");\r
196 #endif  \r
197 \r
198         if((sensor->pdata->irq_enable)&& (sensor->ops->int_status_reg >= 0))    //read sensor intterupt status register\r
199         {\r
200                 \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
203         }\r
204 \r
205         \r
206         //trigger next measurement \r
207         ret = sensor_write_reg(client, sensor->ops->ctrl_reg, sensor->ops->ctrl_data);\r
208         if(ret)\r
209         {\r
210                 printk(KERN_ERR "%s:fail to set ctrl_data:0x%x\n",__func__,sensor->ops->ctrl_data);\r
211                 return ret;\r
212         }\r
213 \r
214         return ret;\r
215 }\r
216 \r
217 static void compass_set_YPR(short *rbuf)\r
218 {\r
219         struct sensor_private_data *sensor =\r
220             (struct sensor_private_data *) i2c_get_clientdata(this_client);     \r
221         \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
229         }\r
230         \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
237                 \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
239         }\r
240         \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
246         \r
247                 DBG("%s:mv_flag:x=%d,y=%d,BRAKE=%d\n",__func__,rbuf[9], rbuf[10], rbuf[11]);\r
248         }\r
249         \r
250         input_sync(sensor->input_dev);\r
251 }\r
252 \r
253 \r
254 \r
255 static int compass_aot_open(struct inode *inode, struct file *file)\r
256 {\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
260 #endif\r
261         int result = 0;\r
262         int flag = 0;\r
263         flag = atomic_read(&open_flag);\r
264         if(!flag)\r
265         {       \r
266                 atomic_set(&open_flag, 1);\r
267                 wake_up(&open_wq);\r
268         }\r
269 \r
270         DBG("%s\n", __func__);\r
271         return result;\r
272 }\r
273 \r
274 \r
275 static int compass_aot_release(struct inode *inode, struct file *file)\r
276 {       \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
280 #endif\r
281         //struct i2c_client *client = this_client;\r
282         int result = 0;\r
283         int flag = 0;\r
284         flag = atomic_read(&open_flag);\r
285         if(flag)\r
286         {\r
287                 atomic_set(&open_flag, 0);\r
288                 wake_up(&open_wq);      \r
289         }\r
290         \r
291         DBG("%s\n", __func__);\r
292         return result;\r
293 }\r
294 \r
295 \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
299 {\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
303 #endif\r
304         void __user *argp = (void __user *)arg;\r
305         int result = 0;\r
306         short flag;\r
307         \r
308         switch (cmd) {\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
313                                 return -EFAULT;\r
314                         }\r
315                         if (flag < 0 || flag > 1) {\r
316                                 return -EINVAL;\r
317                         }\r
318                         break;\r
319                 case ECS_IOCTL_APP_SET_DELAY:\r
320                         if (copy_from_user(&flag, argp, sizeof(flag))) {\r
321                                 return -EFAULT;\r
322                         }\r
323                         break;\r
324                 default:\r
325                         break;\r
326         }\r
327         \r
328         switch (cmd) {\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
332                         break;\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
336                         break;\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
340                         break;\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
344                         break;\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
348                         break;\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
352                         break;\r
353                 case ECS_IOCTL_APP_SET_DELAY:\r
354                         akmd_delay = flag;\r
355                         break;\r
356                 case ECS_IOCTL_APP_GET_DELAY:\r
357                         flag = akmd_delay;\r
358                         break;\r
359                 default:\r
360                         return -ENOTTY;\r
361         }\r
362         \r
363         switch (cmd) {\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
369                                 return -EFAULT;\r
370                         }\r
371                         break;\r
372                 default:\r
373                         break;\r
374         }\r
375 \r
376         return result;\r
377 }\r
378 \r
379 static int compass_dev_open(struct inode *inode, struct file *file)\r
380 {\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
384 #endif\r
385         int result = 0;\r
386         DBG("%s\n",__func__);\r
387 \r
388         return result;\r
389 }\r
390 \r
391 \r
392 static int compass_dev_release(struct inode *inode, struct file *file)\r
393 {\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
397 #endif\r
398         int result = 0; \r
399         DBG("%s\n",__func__);\r
400 \r
401         return result;\r
402 }\r
403 \r
404 static int compass_akm_set_mode(struct i2c_client *client, char mode)\r
405 {\r
406         struct sensor_private_data* sensor = (struct sensor_private_data *)i2c_get_clientdata(this_client); \r
407         int result = 0; \r
408 \r
409         switch(mode)\r
410         {\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
415                         {\r
416                                 if(sensor->pdata->irq_enable)\r
417                                 {\r
418                                         //DBG("%s:enable irq=%d\n",__func__,client->irq);\r
419                                         //enable_irq(client->irq);\r
420                                 }       \r
421                                 else\r
422                                 {\r
423                                         schedule_delayed_work(&sensor->delaywork, msecs_to_jiffies(sensor->pdata->poll_delay_ms));\r
424                                 }\r
425                                 \r
426                                 sensor->status_cur = SENSOR_ON;\r
427                         }\r
428 \r
429                         break;\r
430 \r
431                 case AK8975_MODE_POWERDOWN:     \r
432                         if(sensor->status_cur == SENSOR_ON)\r
433                         {\r
434                                 if(sensor->pdata->irq_enable)\r
435                                 {       \r
436                                         //DBG("%s:disable irq=%d\n",__func__,client->irq);\r
437                                         //disable_irq_nosync(client->irq);//disable irq\r
438                                 }\r
439                                 else\r
440                                 cancel_delayed_work_sync(&sensor->delaywork);   \r
441 \r
442                                 sensor->status_cur = SENSOR_OFF;\r
443                         }\r
444                         break;\r
445 \r
446         }\r
447         \r
448         switch(mode)\r
449         {\r
450                 case AK8975_MODE_SNG_MEASURE:           \r
451                         result = sensor_write_reg(client, sensor->ops->ctrl_reg, AK8975_MODE_SNG_MEASURE);\r
452                         if(result)\r
453                         printk("%s:i2c error,mode=%d\n",__func__,mode);                         \r
454                         break;\r
455                 case AK8975_MODE_SELF_TEST:                     \r
456                         result = sensor_write_reg(client, sensor->ops->ctrl_reg, AK8975_MODE_SELF_TEST);\r
457                         if(result)\r
458                         printk("%s:i2c error,mode=%d\n",__func__,mode);\r
459                         break;\r
460                 case AK8975_MODE_FUSE_ACCESS:\r
461                         result = sensor_write_reg(client, sensor->ops->ctrl_reg, AK8975_MODE_FUSE_ACCESS);\r
462                         if(result)\r
463                         printk("%s:i2c error,mode=%d\n",__func__,mode);\r
464                         break;\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
468                         if(result)\r
469                         printk("%s:i2c error,mode=%d\n",__func__,mode);\r
470                         udelay(100);\r
471                         break;\r
472                 default:\r
473                         printk("%s: Unknown mode(%d)", __func__, mode);\r
474                         result = -EINVAL;\r
475                         break;\r
476         }\r
477         DBG("%s:mode=%d\n",__func__,mode);\r
478         return result;\r
479 \r
480 }\r
481 \r
482 \r
483 static int compass_akm_get_openstatus(void)\r
484 {\r
485         wait_event_interruptible(open_wq, (atomic_read(&open_flag) != 0));\r
486         return atomic_read(&open_flag);\r
487 }\r
488 \r
489 static int compass_akm_get_closestatus(void)\r
490 {\r
491         wait_event_interruptible(open_wq, (atomic_read(&open_flag) <= 0));\r
492         return atomic_read(&open_flag);\r
493 }\r
494 \r
495 \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
499 {\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
503         int result = 0;\r
504         struct akm8975_platform_data compass;\r
505                 \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
514         \r
515         switch (cmd) {\r
516                 case ECS_IOCTL_WRITE:\r
517                 case ECS_IOCTL_READ:\r
518                         if (argp == NULL) {\r
519                                 return -EINVAL;\r
520                         }\r
521                         if (copy_from_user(&rwbuf, argp, sizeof(rwbuf))) {\r
522                                 return -EFAULT;\r
523                         }\r
524                         break;\r
525                 case ECS_IOCTL_SET_MODE:\r
526                         if (argp == NULL) {\r
527                                 return -EINVAL;\r
528                         }\r
529                         if (copy_from_user(&mode, argp, sizeof(mode))) {\r
530                                 return -EFAULT;\r
531                         }\r
532                         break;\r
533                 case ECS_IOCTL_SET_YPR:\r
534                         if (argp == NULL) {\r
535                                 return -EINVAL;\r
536                         }\r
537                         if (copy_from_user(&value, argp, sizeof(value))) {\r
538                                 return -EFAULT;\r
539                         }\r
540                         break;\r
541                 default:\r
542                         break;\r
543         }\r
544         \r
545         switch (cmd) {\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
551                                 return -EINVAL;\r
552                         }\r
553                         ret = sensor_tx_data(client, &rwbuf[1], rwbuf[0]);\r
554                         if (ret < 0) {  \r
555                                 mutex_unlock(&sensor->operation_mutex);         \r
556                                 printk("%s:fait to tx data\n",__func__);\r
557                                 return ret;\r
558                         }                       \r
559                         mutex_unlock(&sensor->operation_mutex);\r
560                         break;\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
567                                 return -EINVAL;\r
568                         }\r
569                         ret = sensor_rx_data(client, &rwbuf[1], rwbuf[0]);\r
570                         if (ret < 0) {  \r
571                                 mutex_unlock(&sensor->operation_mutex);         \r
572                                 printk("%s:fait to rx data\n",__func__);\r
573                                 return ret;\r
574                         }               \r
575                         mutex_unlock(&sensor->operation_mutex);\r
576                         break;\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
581                         {\r
582                                 ret = compass_akm_set_mode(client, mode);\r
583                                 if (ret < 0) {\r
584                                         printk("%s:fait to set mode\n",__func__);               \r
585                                         mutex_unlock(&sensor->operation_mutex);\r
586                                         return ret;\r
587                                 }\r
588                                 \r
589                                 sensor->ops->ctrl_data = mode;\r
590                         }\r
591                         mutex_unlock(&sensor->operation_mutex);\r
592                         break;\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
598                         break;\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
604                         break;\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
608                         break;\r
609                 case ECS_IOCTL_GET_CLOSE_STATUS:
610                         status = compass_akm_get_closestatus(); \r
611                         DBG("%s:closestatus=%d\n",__func__,status);\r
612                         break;\r
613                 case ECS_IOCTL_GET_DELAY:\r
614                         delay = akmd_delay;\r
615                         break;\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
621                         if(ret < 0)\r
622                         {\r
623                                 printk("%s:error,ret=%d\n",__FUNCTION__, ret);\r
624                                 return ret;\r
625                         }\r
626                         break;\r
627                         \r
628                 default:\r
629                         return -ENOTTY;\r
630         }\r
631         \r
632         switch (cmd) {\r
633                 case ECS_IOCTL_READ:\r
634                         if (copy_to_user(argp, &rwbuf, rwbuf[0]+1)) {\r
635                                 return -EFAULT;\r
636                         }\r
637                         break;\r
638                 case ECS_IOCTL_GETDATA:\r
639                         if (copy_to_user(argp, &compass_data, sizeof(compass_data))) {\r
640                                 return -EFAULT;\r
641                         }\r
642                         break;\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
646                                 return -EFAULT;\r
647                         }\r
648                         break;\r
649                 case ECS_IOCTL_GET_DELAY:\r
650                         if (copy_to_user(argp, &delay, sizeof(delay))) {\r
651                                 return -EFAULT;\r
652                         }\r
653                         break;\r
654                 default:\r
655                         break;\r
656         }\r
657 \r
658         return result;\r
659 }\r
660 \r
661 \r
662 static struct file_operations compass_aot_fops =\r
663 {\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
668 };\r
669 \r
670 \r
671 \r
672 static struct miscdevice compass_aot_device =\r
673 {       \r
674         .minor = MISC_DYNAMIC_MINOR,\r
675         .name = "akm8975_aot",\r
676         .fops = &compass_aot_fops,\r
677 };\r
678 \r
679 \r
680 static struct file_operations compass_dev_fops =\r
681 {\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
686 };\r
687 \r
688 \r
689 static struct miscdevice compass_dev_device =\r
690 {       \r
691         .minor = MISC_DYNAMIC_MINOR,\r
692         .name = "akm8975_dev",\r
693         .fops = &compass_dev_fops,\r
694 };\r
695 \r
696 struct sensor_operate akm8975_akm8975_ops = {\r
697         .name                           = "akm8975",\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
713 };\r
714 \r
715 /****************operate according to sensor chip:end************/\r
716 \r
717 //function name should not be changed\r
718 static struct sensor_operate *compass_get_ops(void)\r
719 {\r
720         return &akm8975_akm8975_ops;\r
721 }\r
722 \r
723 \r
724 static int __init compass_akm8975_init(void)\r
725 {\r
726         struct sensor_operate *ops = compass_get_ops();\r
727         int result = 0;\r
728         int type = ops->type;\r
729         result = sensor_register_slave(type, NULL, NULL, compass_get_ops);\r
730 \r
731         result = misc_register(&compass_aot_device);\r
732         if (result < 0) {\r
733                 printk("%s:fail to register misc device %s\n", __func__, compass_aot_device.name);\r
734                 goto error;\r
735         }\r
736 \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
743                         \r
744         DBG("%s\n",__func__);\r
745 error:\r
746         return result;\r
747 }\r
748 \r
749 static void __exit compass_akm8975_exit(void)\r
750 {\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
754 }\r
755 \r
756 \r
757 module_init(compass_akm8975_init);\r
758 module_exit(compass_akm8975_exit);\r
759 \r
760 \r